ASP.NET MVC QuickStart 6: automated testing

…continued from part 5.

Objectives

In this Hands-On Lab, you will be introduced to the ASP.NET MVC framework. In particular, you will:

  • Task 1: add a unit test project
  • Task 2: Test model
  • Task 3: Test controller
  • Task 4: Test routing

System requirements

You must have the following items to complete this lab:

  • Microsoft Visual Studio 2008 SP1 (professional edition)
  • Microsoft ASP.NET MVC 1.0

Prequisites

You must have the following skills to understand this lab:

  • Fundamental knowledge of software development in .NET 3.5
  • Some experience in ASP.NET web development

This lab builds further on the QuickStart 5 code.

Task 1: add a unit test project

In previous QuickStarts we didn’t focus on testing, because the focus was on other aspects of ASP.NET MVC. But one of the biggest advantages of the MVC framework is that you can unit test everything. If you take the test-driven approach, you would first create your tests and then write the code to make those tests pass.

Let’s start off with adding a unit test project: right click the MvcApplication1 solution and select Add -> New project. Select Test Project in Test project types and fill in name and location:

Add new project

Click OK. A test project is now added to your solution:

TestProject1 project

Delete the generated UnitTest1.cs file. Also add a reference to the MvcApplication1 project, and to:

  • System.Web.Mvc
  • System.Web.Abstractions
  • System.Data
  • System.Data.DataSetExtensions
  • System.Web
  • System.Web.Routing

You should test every aspect of you project, in this case this means that you should test:

  • Model (MemberService)
  • Controller action methods (MemberController)
  • Routing

Task 2: Test model

Right click the TestProject1 project and select Add -> New test:

Add new test

Select Unit Test and name it ModelTest.cs. Click OK. Add the following using statement on top of the ModelTest class:

using MvcApplication1.Models;

Then add some unit tests, like:

[TestMethod]
public void Get_Members_Returns_List()
{
var members = MemberService.GetMembers();
Assert.IsNotNull(members, "No members retrieved");
Assert.AreEqual(5, members.Count, "Got wrong number of members");
Assert.AreEqual("Geoffrey", members[0].FirstName);
Assert.AreEqual("Denver", members[0].LastName);
// ...
}
[TestMethod]
public void Delete_Member_Workd()
{
var members_before = MemberService.GetMembers();
MemberService.DeleteMember(members_before[0].ID);
var members_after = MemberService.GetMembers();
Assert.AreEqual(4, members_after.Count, "Member was not deleted");
// ...
}

Run these tests and make sure they pass.

Task 3: Test controller

Add a new unit test to the test project and call it MembersControllerTest. Add the following using statements on top:

using MvcApplication1.Controllers;
using MvcApplication1.Models;
using System.Web.Mvc;

Add the following tests:

[TestMethod]
public void Index_Presents_Correct_Page_Of_Members()
{
MembersController membersController = new MembersController();
ViewResult result = membersController.Index() as ViewResult;

Assert.IsNotNull(result, "Didn't render view");
var members = (IList<Member>)result.ViewData.Model;
Assert.AreEqual(5, members.Count, "Got wrong number of members");
Assert.AreEqual("Geoffrey", members[0].FirstName);
Assert.AreEqual("Denver", members[0].LastName);
}
[TestMethod]
public void Details_Presents_Correct_Page_Of_Member()
{
MembersController membersController = new MembersController();
ViewResult result = membersController.Details(0) as ViewResult;
Assert.IsNotNull(result, "Didn't render view");
var member = ((Member)result.ViewData.Model);
Assert.AreEqual("Geoffrey", member.FirstName);
Assert.AreEqual("Denver", member.LastName);
}

Run these tests and make sure they pass.

Task 4: Test routing

To test routing, we have to mock the request context. To do so, the easiest way is to use a mocking framework, and in this case we will be using moq, which can be downloaded from http://code.google.com/p/moq. Then, from the unit test project, add a reference to Moq.dll.

Add a new unit test and call it InboundRoutingTests.cs. On top of this class, add the following using statements:

using System.Web.Routing;
using MvcApplication1;
using System.Web;

Testing a specific route comes always down to the same:

  • registering the web application’s route collection
  • mocking the request context
  • get the mapped route based in the URL
  • test the mapped route to see if it matches expected values

So we’ll first add a method that accepts a URL and expected routing data values and tests whether the URL routing matches these expected values:

private void TestRoute(string url, object expectedValues)
{
// Arrange: Prepare the route collection and a mock request context
RouteCollection routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var mockHttpContext = new Moq.Mock<HttpContextBase>();
var mockRequest = new Moq.Mock<HttpRequestBase>();
mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
mockRequest.Setup(x =>
x.AppRelativeCurrentExecutionFilePath).Returns(url);
// Act: Get the mapped route
RouteData routeData = routes.GetRouteData(mockHttpContext.Object);
// Assert: Test the route values against expectations
Assert.IsNotNull(routeData);
var expectedDict = new RouteValueDictionary(expectedValues);
foreach (var expectedVal in expectedDict)
{
if (expectedVal.Value == null)
Assert.IsNull(routeData.Values[expectedVal.Key]);
else
Assert.AreEqual(expectedVal.Value.ToString(),

routeData.Values[expectedVal.Key].ToString());
}
}

And finally we can write unit tests to test different routes, for example:

[TestMethod]
public void Slash_Goes_To_All_Members_Page()
{
TestRoute("~/", new
{
controller = "Home",
action = "Index",
id = (string)null,
});
}
[TestMethod]
public void Member2_Goes_To_Member2_Details_Page()
{
TestRoute("~/member2", new
{
controller = "Members",
action = "Details",
id = 2,
});
}

Run these tests and make sure they pass.

Go to next part.

Advertisements

2 thoughts on “ASP.NET MVC QuickStart 6: automated testing

  1. Stephen says:

    I’ve got the latest MVC installed and I do not see the “Test” category when I choose “Add New Project”… I’ve already created an MVC website just fine (and strangely enough as well, i didn’t get prompted to add a Test Project at that time)

    Any ideas?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s