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!

Related posts

Comments

March 20. 2008 13:18

trackback

Trackback from DotNetKicks.com

Asp.net MVC Testing Imbalance

DotNetKicks.com

March 21. 2008 03:53

Maarten Balliauw

When you start testing MVC, you'll probably run into other issues... I posted two of them on my blog: blog.maartenballiauw.be/.../...issues-Q-and-A.aspx

It is indeed strange that 6 lines of controller code mean numerous lines of testing code. But hey, it's only a CTP currently and things may improve. At least I hope too Smile

Maarten Balliauw be

March 21. 2008 08:29

Justin Etheredge

@Maarten Yeah, I'm glad that they are taking their time and developing the MVC framework in a more open process. I think it will really allow them to get it right.

Justin Etheredge us

March 22. 2008 14:01

Daniel Cazzulino

Hi Justin,
thanks for the feedback on Moq.

The complexities you mention are more related to the wiring up of the various pieces of the MVC than Moq, but the point is taken. We're thinking about having additional deliverables on top of Moq that will make this easier, i.e. Moq.MVC, which could include something like a MockContext which already has everything hooked-up and is ready to use.

Feel free to join the project, spike an implementation and set it to us. We're very open to contributions Smile

Thanks!

Daniel Cazzulino ar

March 22. 2008 15:30

Justin Etheredge

@Daniel Honestly I wasn't really trying to critique or offer any feedback on Moq, I guess I didn't make that very apparent. Smile I was more saying that the wiring up of everything to test very simple scenarios in MVC can take quite a bit of effort. Like you said, it wouldn't be any less code in any of the other mocking frameworks, and in some it would have been more.
Since this was my first venture into Moq, I want to say that I really did like the use of lambdas in describing the expectations. I find Moq very easy to work with, and will probably continue to experiment with it.
Also, If you look at the code above, I have created a MockHttpContextContainer that allows me to expose all the different parts of the HttpContext as Mock<T> so that I can set my needed expectations for things like form data. I was going to add more helper methods and whatnot on there, is that something similar to what you were considering building?

Justin Etheredge us

March 23. 2008 01:01

trackback

Trackback from CodeThinked

Simplified Asp.net MVC Controller Testing with Moq

CodeThinked

March 25. 2008 12:46

Chris

Justin,

I've learned that writing maintainable tests requires just as much dedication and creativity as writing maintainable functional code. I found the book "xUnit Test Patterns: Refactoring Test Code" to be very helpful.

Also, the "Object Mother" pattern could be used in your example for thinning the code in the actual test case.

Chris

Chris us

March 25. 2008 12:56

Justin Etheredge

@Chris I agree completely, people will only test as long as it is easy for them to test. In fact, this applies to most everything. It either has to be easy or they have to have no other option. And I will look at the "Object Mother" pattern and how it might help me with my testing. Thanks.

Justin Etheredge us

March 31. 2008 15:02

pingback

Pingback from code-inside.de

Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog

code-inside.de

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

May 13. 2008 14:03