Extending Steve Sanderson’s ContextMocks class

July 27, 2009

I’ve been working on unit testing ASP.NET MVC Controller actions and have been using the ContextMocks and other fake classes Steve Sanderson provided in his excellent book, Pro ASP.NET MVC Framework. It’s literally under 50 lines of code and uses Moq to supply just enough context to your controller actions so you can test without fireworks.

Thus far I’ve had to extend Steve’s solution twice: Ability to set and access User.Identity.Name (username of the authenticated user) and the ability to set and access the HttpMethod (GET, POST…). If you’ve been following along the book and need to take advantage of these properties in your unit tests, then this post is for you. Note: I will not be including full source code – only the code I’ve added. Unfortunately this may not make complete sense if you aren’t aware of Steve’s implementation.

Setting the User.Identity.Name

Specifying the User.Identity.Name is done just like the other Setup methods on HttpContext, something you could either do right in your ContextMocks constructor, or in a separate method like the one below:

public void SetupContextUser(string UserName)
{
    HttpContext.Setup(x => x.User).Returns(new FakePrincipal(new FakeIdentity(UserName)));
}

This should be pretty straightforward except for the FakePrincipal and FakeIdentity… what’s that all about? The Identity in User.Identity.Name implements the interface IIdentity, and the Name in User.Identity.Name implements IPrincipal.  While perhaps not the only option, what I ended up doing is creating a fake class for each, just implementing the bare minimum:

private class FakePrincipal : IPrincipal
{
    private FakeIdentity _ident;
    public FakePrincipal(FakeIdentity ident)
    {
        _ident = ident;
    }

    #region IPrincipal Members

    public IIdentity Identity
    {
        get { return _ident; }
    }

    public bool IsInRole(string role)
    {
        throw new NotImplementedException();
    }

    #endregion
}

private class FakeIdentity : IIdentity
{
    private string _name;
    public FakeIdentity(string Name)
    {
        _name = Name;
    }

    #region IIdentity Members

    public string AuthenticationType
    {
        get { throw new NotImplementedException(); }
    }

    public bool IsAuthenticated
    {
        get { throw new NotImplementedException(); }
    }

    public string Name
    {
        get { return _name; }
    }

    #endregion
}

Passing in these fake objects (along with your provided username of choice) into the Moq setup method for HttpContext is all there is to it! Now if your controller accesses this.User.Identity.Name in any of its methods, your unit tests such as the one below will work!

[Test]
public void Test_unit_test()
{
    var mocks = new ContextMocks(controller);
    mocks.SetupContextUser("10001");
    var result = controller.Index(); //wont blow up!
    //...
}

Setting the HttpMethod

This is pretty easy, and frankly, probably an unlikely thing to need. I stupidly implemented my solution thinking it was required to properly test my [AcceptVerbs(HttpVerbs.Post)] methods, when in fact it’s not! These methods all have a unique signature by default and running from a test system (and not MVC itself) they serve no function.

Still, your controllers may access Request.HttpMethod and in such a case, you’ll need to specify this in your mocked Request object. My solution was to make an overloaded constructor on the ContextMocks class, like so: (everything else in this method has been omitted for brevity)

public ContextMocks(Controller onController, string HTTPMethod)
{
    //...
    Request = new Moq.Mock<HttpRequestBase>();
    Request.Setup(x => x.HttpMethod).Returns(HTTPMethod);
    //...
}

Create a test like so, and you’re in business. Your controller can access Request.HttpMethod and it will have an appropriate value provided by your test!

[Test]
public void another_test_test()
{
    var mocks = new ContextMocks(controller, "POST");
    var result = controller.Index();
    Assert.IsNotNull(result);
}

Hope this helps!

Unit testing your privates and internals

July 7, 2009

After spending more time with unit testing and this whole TDD thing, I’ve hit a barrier I wasn’t sure how to cross. How do you test internal and private members?

Before you even consider how to do so, you might consider why you are doing so. As Brody points out:

In theory you should only need to test your public methods anyway. Just have enough tests that you are testing all the code paths. In reality you may want to verify something works as expected before calling it with a whole lot more code.

If you are using TDD (Test Driven Development) this is not usually an issue as no code is written without a test so no code path should remain untested. Internal, protected and private methods are then spawned as you refactor against your existing tests.

Yes, I really need to test that

In my recent case, not only did I need to verify that each (internal) component of an algorithm I was developing, but this was the only way to test the algorithm. Due to it’s nature – a randomizer that causes no result to be guaranteed, it’s simply impossible to test the thing as a whole.

Okay, maybe not impossible. I suppose the randomizer could be implemented with an Interface that is mocked/faked and provided by the unit test… but I’m not going there.

Exposing  internal methods with InternalsVisibleTo

Exposing your private methods is relatively easy. Just add:

[assembly:InternalsVisibleTo("UnitTestAssembly")]

to the AssemblyInfo.cs file of the assembly you want to access internal methods of. This will allow the assembly “UnitTestAssembly” - in this case - to see them. Unfortunately, this has no effect on private methods.  Refer to Friend Assemblies.

Exposing private methods with PrivateObject

This was new to me pointed out by Emad Ibrahim in a recent blog post, but Microsoft already has an implementation to achieve this. The Microsoft.VisualStudio.QualityTools.UnitTestFramework assembly included with a Visual Studio test project (but not of course, if you built your own unit test assembly and use NUnit, for instance) has a class called PrivateObject which does the magic:

MyClass myObj = new MyClass();
var po = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(myObj);
string returnStr = (string)po.Invoke("DoSomethingPrivate");

It’s pretty simple – Instantiate your object that contains the private methods you need to test, create an instance of PrivateObject, passing in your object, and then calling PrivateObject’s Invoke() method, specifying the private method name.

With these workarounds, now any method can be unit tested regardless of it’s access modifier.

Creating an ActionResult that returns XML with ASP.NET MVC

July 2, 2009

In the past, with Webforms, whenever I needed a page to return a pure XML document to the browser I’d end up doing it something like this copied from page to page:

Response.Clear();
Response.ContentType = "text/xml";
Response.Write(myXml.ToString());
Response.End();

Frankly, this is more than sufficient, but when it came to doing the same thing with ASP.NET MVC it just didn’t seem right. Is this “separation of concerns” thing getting to me? You wouldn’t implement this code in the View, and it seems inappropriate to handle this within a controller Action (though you could). How about an ActionResult?

MvcContrib.ActionResults.XmlResult

I was a bit surprised to find this wasn’t already built into the core ASP.NET MVC framework so I set out to create my own, and in turn, found out one exists in the MVC Contrib project.

The XmlResult class is very simple. It inherits ActionResult and overrides the ExecuteResult method, where the XML is serialized and outputted to the response stream. Here’s a stripped down copy of the MvcContrib implementation:

public class XmlResult : ActionResult
{
    private object _objectToSerialize;

    public XmlResult(object objectToSerialize)
    {
        _objectToSerialize = objectToSerialize;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (_objectToSerialize != null)
        {
            var xs = new XmlSerializer(_objectToSerialize.GetType());
            context.HttpContext.Response.ContentType = "text/xml";
            xs.Serialize(context.HttpContext.Response.Output, _objectToSerialize);
        }
    }
}

XmlResult in action

To make use of this, you merely have to return a new instance of an XmlResult object within your Controller action, passing it the object you want to be serialized to XML. Here’s how it would look if I were wanting to output a useless document created with the new magic that is System.Xml.Linq:

public ActionResult Index()
{
    XElement root = new XElement("root");
    root.Add(new XElement("element1"));
    root.Add(new XElement("element2"));
    root.Add(new XAttribute("attribute1", "a value"));
    return new XmlResult(root);
}

And, as expected, if this particular Controller Action was requested in your browser, you’d see the following result:

image

Stay tuned for a following post that will make further use of this cool action result!

About me

I'm Kurt, and I make web applications. Want to know more? Check out my about page.

WTF is all this code? I came here for food!

My wife made a new year's resolution to try out at least one new recipe each week. Want to know what she's been feeding me? resolutionfood.blogspot.com