Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Derik Whittaker

Thoughts on Software Development, .Net, OOP, Design Patterns and all things cool



Testing controller actions inside ASP.Net MVC

***** DISCLAIMER *****
The techniques and information here were not all thought up by me.  I got a lot of this from Scott Hanselman's screencasts, and at looking at other MVC projects.  I am only putting this into a post to have a single point of reference for the next guy.
***** END DISCLAIMER *****

One of the main goals of the new ASP.Net MVC framework is to allow for easier testing of web applications.  One of the things that is now easily testable is controller actions. 

Before we get started, there are a few things you are going to need in order to test controller actions.

  1. RhinoMocks (or any other mocking framework)
  2. The MVCMockHelper from Phil Haack
  3. A fake view Engine to use
    public class FakeViewEngine : IViewEngine
    {
        public ViewContext ViewContext { get; private set; }
    
        public void RenderView(ViewContext viewContext)
        {
            ViewContext = viewContext;
        }
    }
    

Ok, on to the actual test code.

[Test]
public void SportsEdit_Verify_Correct_Actions()
{
    // Point 1
    MockRepository mocker = new MockRepository();
    ISportService sportServiceMock = mocker.CreateMock();
    
    SportsController myController = new SportsController();
    FakeViewEngine fakeViewEngine = new FakeViewEngine();
    myController.ViewEngine = fakeViewEngine;

    // Point 2
    // Create my mock sport to be returned
    Sports sportsMock = mocker.CreateMock(new Sport {SportID = 1, Description = "Desc", Name = "Name"});

    // Point 3
    // Tell StuctureMap we want a mock, not the real thing
    ObjectFactory.InjectStub(typeof(ISportService), sportServiceMock);

    // Point 4
    // setup the expectation on my call into my service
    Expect.Call(sportServiceMock.GetSports(1)).IgnoreArguments().Return( sportsMock );

    // Point 5
    // Setup all expectations for the mocking engine
    mocker.SetFakeControllerContext(myController);
    mocker.ReplayAll();

    // Point 6            
    // call the actual controller method.
    myController.SportsDetails( 1 );

    // Point 7
    Assert.That( "SportsEdit", Is.EqualTo( fakeViewEngine.ViewContext.ViewName ) );
    Assert.That(sportsMock, Is.EqualTo(fakeViewEngine.ViewContext.ViewData));
            
}

I will break the code above into multiple sections to better explain what is going on.

  1. Here we are setting up the mock engine and creating any objects that are going to be needed during the test later.
  2. Need to create the object to return later during our expected call via our service
  3. Need to tell StructureMap what to do when someone asks for a ISportService.  In this case we want to mock it out since we DO NOT want to do a round trip.
  4. Setup the correct expectation on the mock service (needed to avoid the round trip)
  5. This is the important step, this is where we are making use of the MVCMocking helper stuff.  In here we are going to setup all sorts of mocks for later use.
    NOTE - If you forget this step you will get a NullReference exception when calling your controller
  6. Make the call into the actual controller.  This is testing the call as if it were being called by the IIS during the controller call.
  7. We are asserting that the correct view name is being called and we have passed along the correct view data as well.

I am pretty sure there are other ways to test controller actions.  In fact I have seen them.  But so far this is my favorite way.

Let me know what you think.

Till next time,



Comments

Links Today (2008-03-09) said:

Pingback from  Links Today (2008-03-09)

# March 9, 2008 11:17 AM

Dew Drop - March 9, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - March 9, 2008 | Alvin Ashcraft's Morning Dew

# March 9, 2008 3:22 PM

CodeThinked said:

Simplified Asp.net MVC Controller Testing with Moq

# March 23, 2008 1:01 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Derik Whittaker

Derik is a .Net Developer/Architect specializing in WinForms working out the northern suburbs of Chicago. He is also believer and advocate for Agile development including SCRUM, TDD, CI, etc.

When Derik is not writing code he can be found spending time with his wife and young son, climbing on his bouldering wall, watching sports (mostly baseball), and generally vegging out. Check out Devlicio.us!

Our Sponsors

Red-Gate!