One of the key benefits of the MVC (Model View Controller) pattern is a separation of concerns that leads to better testability. Microsoft recognizes this and will automatically create a separate MS Test project when creating a new ASP.NET MVC solution. While this gives you a nice head start, there's room for improvement. While actions in the MVC pattern are simply methods on a class that can easily be called by MSTest (or any unit testing framework), most web applications have interactions with supporting objects such a Request (query string, form parameters, etc…), Response (cookies, content type, headers, etc…), Session, and more. In a live environment, these objects come as a result of the HTTP request being processed by IIS. In a test environment, you're isolating just your controllers and actions and you don't have IIS and an entire HTTP pipeline. We can use mocking to provide "pretend" implementations of all of these objects, but there's a lot to mock. This is where the MVC Contrib project on CodePlex can really come in handy! MVC Contrib Test Helper The MVC Contrib project gets a lot of praise for the many benefits it brings when developing for ASP.NET MVC – numerous UI helpers, Model Binders, Controller factories, etc… But it also contains a TestHelper library that makes unit testing your controllers much easier. By utilizing Rhino.Mocks , the MVC Contrib TestHelper can create and initialize your controller with mocked instances of: HttpRequest HttpResponse HttpSession Form HttpContext and more! In this article, I'll utilize the MVC Contrib TestHelper library to fully unit test a simple ASP.NET MVC controller. As with many small demos, it's totally contrived, but helps illustrate the principals. Scenario We're building an ASP.NET MVC project that has to accept submissions from speakers. We'll be doing this in a "wizard-like" fashion. The prospective speaker will first enter their personal information (first name and last name). The next step will have them enter their submission information. There will be a final review point and finally, the actual submission. Since some speakers want to submit multiple talks, we'll re-display the speakers personal information if they start the wizard up again after submitting a talk. Design In this article, we're only going to deal with the first step: collecting the speakers personal information (first name and last name). We'll save this information in the Session object and pull it back out if the speaker returns to the beginning of the wizard after submitting a talk. Both the speakers first name and last name are required – the user can not continue if they aren't both filled in. The action on the controller is the "Speaker" action. The next step in the wizard is the "SessionDetails" action. Using the information above, we have 5 test scenarios to cover: If we run the "Speaker" action with nothing in the Session: The result should be a ViewModel which has no speaker first name/last name and we should return a "View" result to ASP.NET MVC. If we run the "Speaker" action with a first name/last name in the Session: The result should be a ViewModel which as the first name/last name from the Session and should return a "View" result to ASP.NET MVC. If we run the "Speaker" action and only send in a first name: We should save the first name to the Session, but we'll also add an error for the missing last name to the ModelState and return a "Redirect" result so ASP.NET MVC will go back to the "Speaker" action and give the user the chance to enter their missing last name. Do the same test as above, but for the last name. If we run the "Speaker" action and send both a first name and a last name: The first and last name should be saved to the Session object and a "Redirect" result should be returned that tells ASP.NET MVC to go to the "SessionDetails" action. Set Up Start up a new ASP.NET MVC project and make sure you select the option to create unit tests. The default ASP.NET MVC project comes with a Home controller. For simplicity's sake, we'll add our actions to that controller and add our tests to the HomeControllerTests class. First, let's create a class to maintain our speaker information. Sure, it's only two pieces of information, but this is a sample. In the real world, we'd probably have more than this and therefore, we'll use a class: public class SpeakerInfo { public string FirstName { get; set; } public string LastName { get; set; } } Test #1 We start by writing our failing test (red), we'll throw together enough production code to get the test to pass (green), then we'll implement our actual logic and make sure...