CodeThinked

codethinked (kōdthĭngked) adj. To be consumed by or obsessed with code.

Asp.net MVC Testing Imbalance

Update: I have put up a new post here that shows how I have simplified some of my testing. If you like it please kick it so that others will see the follow up post!

Here is my "Update" action on a project that I am working on:

public void Update(int id)
{
    _viewData.User = _userRepository.GetUser(id);
    BindingHelperExtensions
        .UpdateFrom(_viewData.User, Request.Form);
    _userRepository.SubmitChanges();
 
    RedirectToAction("List");
}

And here is my test for it (using Moq, I wanted to try it out. This uses the Moq MvcMockHelpers from Scott Hanselman's post):

public void UserControllerUpdateTest()
{
    RouteTable.Routes.Add(
        new Route("[controller]/[action]", new MvcRouteHandler()));
 
    var mockUserRepository = new Mock<IUserRepository>();
 
    var user = new User()
    {
        Id = 10,
        UserName = "TestUser",
        EmailAddress = "test@test.com",
        ModifiedOn = DateTime.Now,
        CreatedOn = DateTime.Now
    };
 
    mockUserRepository.Expect(ur => ur.GetUser(10))
        .Returns(user);
    mockUserRepository.Expect(ur => ur.SubmitChanges());
 
    var fakeController = 
        new UserControllerForTesting(mockUserRepository.Object);
    FakeViewEngine fakeView = new FakeViewEngine();
    fakeController.ViewEngine = fakeView;
 
    var context = new MockHttpContextContainer();
 
    var formData = new NameValueCollection();
 
    var userNameFormData = "TestUser2";
    var emailAddressFormData = "test2@test.com";
 
    formData.Add("User.UserName", userNameFormData);
    formData.Add("User.EmailAddress", emailAddressFormData);
 
    context.Request.Expect(r => r.Form)
        .Returns(formData);
 
    var routeData = new RouteData();
    routeData.Values.Add("Action", "Add");
    routeData.Values.Add("Controller", "Home");
    fakeController
        .SetFakeControllerContext(context.Context.Object, 
        routeData);    
 
    fakeController.Update(10);
 
    mockUserRepository.VerifyAll();
 
    Assert.AreEqual(fakeController.RedirectedAction, "List");
    var viewData = fakeController.TestingViewData;
    Assert.IsNotNull(viewData);
    Assert.IsNotNull(viewData.User);
    Assert.AreEqual(viewData.User.UserName, 
        userNameFormData);
    Assert.AreEqual(viewData.User.EmailAddress, 
        emailAddressFormData);
}

And that doesn't even include any of my helper objects or methods. Anyone see a problem with this? I am going to have to put some serious effort into streamlining this. I know that there is quite a bit I can abstract out across different controllers and actions so we will see how this goes. Feel free to provide feedback if you like. So far though I am really having fun digging into this, I can't believe I waited this long!