The Ultimate Guide To Unit Testing in ASP

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 12

The Ultimate Guide to Unit Testing in ASP.

NET MVC
With most development, you need checks-and-balances with your application. Today, I
show you what makes unit testing great and the best ways to achieve exceptional unit
test coverage in your ASP.NET MVC application.

Unit tests are definitely becoming a need-to-have skill for developers to confirm their code does what it should for
production.
If you aren't building unit tests for your code, I would suggest looking into unit test libraries and frameworks along
with a mocking framework to intercept external calls to other resources.
I used to be one of the developers who poo-poo'd unit tests, but now, I can't live without them. They're a way to
perform checks-and-balances on your code.
Personally, there have been two instances that have changed my way of thinking with unit tests:

There was a large C# system that was missing a simple, but critical business rule (but it really wasn't). The
manager said that they weren't going to compensate me because it wasn't coded. I opened my unit tests and
ran specific unit test to show them the code and that it was working as expected. Luckily, the code was a
very simple unit test with three lines and the client understood the unit test. He was convinced that I did
code it and that it functioned properly. After the incident, I was promptly compensated.

I wrote a validation engine for a company that had an insane amount of validations. Right before we
finished the validation engine, we had a large amount of unit tests backing the functionality of the engine
so if something was coded wrong or something was modified in the validation engine, the unit test would
catch it. At one point, we needed to refactor the code. The great part about this is that it took me two days
to refactor the code...and by the end of those two days, all of the existing unit tests passed except one. The
one unit test needed adjusting because of the new syntax, but after modifying the unit test, all unit tests
passed successfully. All Green! If I didn't have all of those unit tests, I would've been rewriting the code
blindly.

As you can see, these unit tests solve a number of issues in their own way.
Let's get into the basics of different types of testing.
Terminology

The basics of testing can be broken into the following categories:

Unit Testing
This type of testing is meant to focus on one unit of code, usually a class or a method and assure the
developer that the proper expected behavior is returned.

Integration Testing
Integration Testing is when a program accesses an external resource to confirm that the code is functioning
properly (i.e. database calls or loading a file). If you are making database calls in your unit tests, then
they aren't called unit tests...they are integration tests.

Regression Testing
Over time, as your system grows, you accumulate more and more unit tests. Those old unit tests need to
run just like the new ones. Regression testing is finding defects after a major code change has occurred.
Those old unit tests may need refactored to match the new code. Of course, if it is new code, I could almost
Page 1 of 12

guarantee that at least 25-50% of your unit test code would fail (considering it's a major change to your
code base).

Load Testing
After your website is built, you may need to perform some load testing to determine the stamina of your
code. What I mean is that load testing is primarily concerned with how well the system runs under a
specific load of users or large amounts of data.

With those terms explained, the unit tests and integration tests are the most important for this particular post,
but trust me, there are a ton of different software testing methods!
Everyone, and I mean everyone, in the IT industry is testing the quality of their products. From the first line of
code a developer writes to the last power user giving their stamp-of-approval before it heads out the door...
...Everyone is a part of QA now (in one way or another)!
What are some general guidelines for Unit Testing?

Based on my experiences, here are some of my guidelines I've learned over the years.

Make sure you unit tests tests what needs to be unit tested...and nothing more.
If you have a simple POCO (Plain Old CLR Object) with a list of properties with no implementation or
business rules behind it, I'm guessing you don't need to test it.

Your code should be unit testable. If it's not, you may need to rethink your design.
Sometimes, it's a good idea to write your unit test first. That way, you get a clear understanding and
perspective of how developers will interact with your code. If it's not clear in your unit test, what makes
you think that developers will understand it in production? ;-)

You really don't need to mock everything.


Some users mock the heck out of everything because they can. For example, your business objects. No
mocking is necessary. You can new one up just to see if code is structurally sound and passes a specific
business requirement.

If a business routine or rule is really complex, write unit tests around it (or take a hammer to it).
Confirm the nature of the routine by writing unit tests. If it's really complicated and it's a long method,
"break" it into manageable pieces of code. Breaking this code smell into manageable chunks of code will
accomplish two things: smaller, testable routines for unit testing and a better understanding of the code
since it's refactored.

Write small unit tests to achieve quick wins


I've seen a number of developers write elaborate unit tests showing 50 lines of code to return back one
number. Remember when I said your unit tests will show developers how complex your system is? While
50 or more lines of code in a unit test is definitely a design problem/code smell, the best unit tests focus on
smaller parts of the system and achieve better granularity across the system components.

Use as many Asserts to confirm the behavior works as expected


I've heard a number of developers argue that you need only one Assert per unit test. I disagree. You may
return a number of parameters in a ViewModel that HAS to have a list of records, a total, and a page title. I
would not make three methods to check each one separately. I would create one unit test with three Asserts.

Of course, unit testing can be specific to individuals or even a company culture.


Page 2 of 12

Does anyone feel the same way? Post your comments below. Give me your thoughts.
So How Does Unit Testing Work in ASP.NET MVC?

This was one of the selling points with ASP.NET MVC for me. The structure of an MVC project is already testable
right out of the box.
Once you start Visual Studio and create your first ASP.NET MVC project, you can start writing unit tests before
you write any code.
Usually, you create a separate unit test project for each project.
I follow the Given/When/Then method of writing unit tests where:

Given is the name of the folder

When is the name of .cs file

and Then is the name of each method name explaining the behavior of the unit test.

You'll see some examples below when we get to each MVC term.
How Do You Unit Test HttpContext and the Database?

Ahh the age old question about HttpContext...How can you mock HttpContext?
Mocking an HttpContext can be difficult to mock because you are expecting a certain result from server variables
or referring urls. How do you test against an environment-based object?
Luckily, I already mentioned this in a previous post called How to Successfully Mock HttpContext that describes
all of the ways to return relevant HTTP data back in your unit tests.
As for the database, I was able to come up with a way to mock a database relatively quick.
Finally, The ASP.NET MVC Unit Tests

Since there's a lot of technology "hooks" in ASP.NET MVC and I want to go over all of them with their
corresponding unit tests.
Now let's get into some MVC unit testing.
Controllers

Controllers are the workhorses of MVC. The behavior we want to test with controllers are the action results or
view model returned from them.
GivenAnAboutController\WhenRequestingTheAboutPage.cs
[TestClass]
public class WhenRequestingTheAboutPage
{
[TestMethod]
public void ThenReturnTheAboutViewModel()
{
// Arrange
var controller = new AboutController();

Page 3 of 12

// Act
// No database calls in the Index() method.
// Just setting the title.
var result = controller.Index() as ViewResult;
var model = result.Model as AboutViewModel;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual("About DanylkoWeb", model.Title);

This is the simplest you can get from a controller. You pass a model into the View and it replaces what it needs to
on the View.
But we all know that most controllers aren't this simple. We are accessing a database or something inside the
controller, right?
Something like this:
public class FaqController : Controller
{
private readonly IFaqRepository _repository;
public FaqController(): this(new FaqRepository()) { }
public FaqController(IFaqRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var records = _repository.GetAll();
var model = new FaqViewModel
{
FAQs = records
};
return View(model);
}
}

We need to mock up a FaqRepository. So how do we do that? Using a mock framework. I used to use
RhinoMocks, but switched over to Moq.
Here is how we would mock up a FaqRepository.
[TestMethod]
public void ThenReturnTheFaqViewModel()
{
// Arrange
var faqs = new List<Faq>
{
new Faq {Id = "1", Answer = "Home", Question = "Where Do you Live?"},
new Faq {Id = "2", Answer = "Since I was 11", Question = "When did you start programming?"},
new Faq {Id = "3", Answer = "In Pennsylvania", Question = "Where were you born?"}
};
var faqRepository = new Mock<IFaqRepository>();
faqRepository.Setup(e => e.GetAll()).Returns(faqs.AsQueryable());
var controller = new FaqController(faqRepository.Object);
// Act
var result = controller.Index() as ViewResult;
var model = result.Model as FaqViewModel;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(3, model.FAQs.Count());
}

Whatever is passed into your controller or new'ed up in your controller that accesses data, make sure you can
mock it up (not MUCK it up) and pass it in.

Page 4 of 12

Action Filters

ActionFilters are attributes on each action method in a controller. This is where we experience HttpContext
occurrences so we need a mocked up HttpContext, which can be found here.
Let's look at the SearchBotFilter we wrote a while back as an example.
public class SearchBotFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.Browser.Crawler)
{
filterContext.Result = new ViewResult() { ViewName = "NotFound" };
}
}
}

This isn't that intimidating. We just need to confirm that the value returned is the right ViewName.
[TestMethod]
public void ThenConfirmAuthorizationActionFilterWorkedAsExpected()
{
// Arrange
var moqContext = new Mock<HttpContextBase>();
var moqRequest = new Mock<HttpRequestBase>();
moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
moqContext.Setup(x => x.Request.Browser.Crawler).Returns(true);
var raa = new SearchBotFilter();
var filterContextMock = new Mock<ActionExecutedContext>();
var viewResultMock = new Mock<ViewResultBase>();
filterContextMock.Object.Result = viewResultMock.Object;
filterContextMock.Setup(e => e.HttpContext).Returns(moqContext.Object);
// Act
raa.OnActionExecuted(filterContextMock.Object);
var viewResult = filterContextMock.Object.Result as ViewResult;
// Assert
Assert.IsTrue(viewResult.ViewName == "NotFound");
}

Action Results

Action Results are used to return the proper data to a View. The expected behavior for ActionResults is to
determine the proper model sent to the View.
[TestMethod]
public void AboutIndexTest()
{
// Arrange
var controller = new AboutController();
// Act
var result = controller.Index();
// Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
var viewResult = result as ViewResult;
Assert.AreEqual(typeof(AboutViewModel), viewResult);
}

You can optionally check that the proper model is returned as well.
Model Binders

If you are posting data back to an action method in a controller and the data in the form requires a specific model
(i.e. Uploading a file), you can easily use ModelBinders to package everything into a nice model to pass it into a
controller. The behavior expected is a model passed into the controller.
Page 5 of 12

I posted about unit testing ASP.NET MVC model binders in a past post so I defer you to that post. :-)
UrlHelpers

UrlHelpers are great for cataloging your web application with Urls. We expect a string returned based on
parameters passed into the UrlHelper.
There is one problem with UrlHelpers...they take a lot of setup to retrieve the Url to properly test.
Let me show you what I mean.
[TestMethod]
public void ThenVerifyTheRightLoginUrlIsReturned()
{
// Arrange
var routes = new RouteCollection();
RouteTable.Routes.Clear();
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/login", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new NameValueCollection());
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier("/login")).Returns("http://localhost/login");
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
var controller = new LoginController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
// Act
var login = controller.Url.LoginUrl();
// Assert
Assert.AreEqual("/Login", login);
}

See what I mean? It would be easier to create an TestInitialize at the top containing all of this plumbing and just
issue it once.
HtmlHelpers

HtmlHelpers are used for returning properly-formatted HTML snippets of code. The behavior we are expecting
back is properly-formatted HTML based on criteria passed into the helper.
HtmlHelpers are no better. They also take a lot of set up to unit test properly. I would also like to thank Thomas
Ardel for his HtmlHelper routine. Awesome work, sir! :-)
[TestMethod]
public void ThenVerifyTheRightLoginUrlIsReturned()
{
// Arrange
var faq = new Faq
{
Id = "2",
Answer = "Home",
Question = "Where do you live?"
};
HtmlHelper helper = CreateHtmlHelper<Faq>(
new ViewDataDictionary(faq));

// Act
var result = helper.EditFAQItem(faq);
// Assert
Assert.AreEqual("<a href=\"#2\">Faq Item #2</a>", result);

public HtmlHelper<T> CreateHtmlHelper<T>(ViewDataDictionary viewData)


{
var cc = new Mock<ControllerContext>(

Page 6 of 12

new Mock<HttpContextBase>().Object,
new RouteData(),
new Mock<ControllerBase>().Object);
var mockViewContext = new Mock<ViewContext>(
cc.Object,
new Mock<IView>().Object,
viewData,
new TempDataDictionary(),
TextWriter.Null);
var mockViewDataContainer = new Mock<IViewDataContainer>();
mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);
return new HtmlHelper<T>(
mockViewContext.Object, mockViewDataContainer.Object);
}

A lot of work is required, but it can be tested!


Routes

Routing tells MVC which controller to use when a Url is entered. The expected behavior of a route is to know the
controller, action, and optional id for when a Url comes in.
I discussed the routing unit testing in the post called How to Successfully Mock HttpContext (Yes, the same one
from above).
The routing is pretty simple.
Repository and Unit of Work (with Entity Framework)

The Repository and Unit of Work design patterns are great for accessing your databases. So how do you test the
database without connecting to it?
The first thing you need is to create each of your mocking components from the lowest to the highest.
Our first thing we need is the "database." When I say database, I mean an in-memory table that provides the
functionality we need for our unit test to pass. Of course, there are quicker ways to mock up a database.
For now, we'll use a simple in-Memory database using a mocked-up DbContext.
You may be wondering why we created a "fake" DbContext. The whole idea is to create a fake DbContext so we
can test the Repository pattern and Unit of Work. That's the goal for mocking up a DbContext.
[TestMethod]
public void ThenReturnAllMenuItemsTest()
{
// Arrange

// __context is a Mocked DbContext created with Moq


// Create our repository by passing in our DbContext.
var mockMenuRepository = new Mock<MenuRepository>(_context.Object);
// Mock unit of work has a lot of repositories in it.
// We pass the context into the Unit of Work.
var mockUnitOfWork = new Mock<BaseUnitOfWork>(_context.Object);

// If we call our MenuRepository in our unit of work, we return a mocked up MenuRepository.


mockUnitOfWork.Setup(e => e.MenuRepository).Returns(mockMenuRepository.Object);
// Act
var menuItems = mockUnitOfWork.Object.MenuRepository.GetAll();
// Assert
Assert.AreEqual(5, menuItems.Count());

By setting up the three items to make a complete database call (DbContext, Repository, and Unit of Work), you
can create an in-memory database of records to test any scenario that arises in a production environment.
Conclusion

After everything we covered in this post, there are always more ways to add unit tests for additional code
coverage.

Page 7 of 12

The great thing about ASP.NET MVC is that everything in the framework is unit testable. Of course, you can paint
yourself into a corner if your design isn't completely flushed out and well understood.
If I missed any ASP.NET MVC technology that wasn't covered here, post a comment so we can get it into this
Ultimate Guide to Unit Testing in ASP.NET MVC.

How to Successfully Mock HttpContext


For web developers, mocking an HttpContext is one of the hardest things to do. Today, I use two
mocking frameworks to show you a number of ways to mock the HttpContext.

Since I've been using ASP.NET MVC, I've learned a lot about unit testing in the past 5 years (and a lot of that
credit goes to Jon Kruger), but with all of that learning, I keep hearing about developers who have trouble with
mocking HttpContext.
You always need to make sure that your code runs as independent as possible. Your environment can, and
will, change. Therefore, you need to match the environment as much as possible to make your code work in an
environment that isn't connected.
An environment that isn't connected? Whaaaaaat? What does that mean?
Your unit tests should run with no external resources. Zip. Zilch. Nada. None!
If you are connecting to a database, these are called integration tests. The database can be down for maintenance
and your unit tests would fail.
Same for files on a hard drive. Integration test. The file is mandatory or the hard drive fills up and runs out of
space. Unit test fails.
Same for accessing the Internet. External resource...integration test. Network is down. Dead unit test.
Unit tests should run on a machine with no connections to any external resources. Period.
Mocking Frameworks
So how do we test HttpContext without connecting to the Internet?
That is where our mocking frameworks enter the picture: Moq and RhinoMocks.
Both are important, but I think Moq is taking the lead based on the strong typing syntax instead of
RhinoMocks' magic strings.
To show the similarities, I will be providing both Moq and Rhino Mocks examples.
Time to Mock the HttpContext
When we mock an object, what we are really saying is that we are creating dummy objects that
mimic the behavior of real objects in our system. We want our dummy objects to act just like we're
are using them in a production environment.
The baseline for mocking the HttpContext is pretty simple. We attach our TestInitialize attribute to
our method and create our variables.
Page 8 of 12

[TestClass]
public class MockingHttpContextTest
{
private HttpContextBase rmContext;
private HttpRequestBase rmRequest;
private Mock<HttpContextBase> moqContext;
private Mock<HttpRequestBase> moqRequest;
[TestInitialize]
public void SetupTests() {
// Setup Rhino Mocks
rmContext = MockRepository.GenerateMock<HttpContextBase>();
rmRequest = MockRepository.GenerateMock<HttpRequestBase>();
rmContext.Stub(x => x.Request).Return(rmRequest);
// Setup Moq
moqContext = new Mock<HttpContextBase>();
moqRequest = new Mock<HttpRequestBase>();
moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
}

Now we can start mocking our ASP.NET MVC routines very easily with a mocked-up HttpContext.
Routing
Since routing is deconstructed from the HttpContext, unit testing routes makes things a little more
difficult, but we have a mocked HttpContext!
Routing is strictly used from the AppRelativeCurrentExecutionFilePath property (Phew! that's a
mouthful) so we need to mock just that property.
#region Routing Tests
[TestMethod]
public void RhinoMocksRoutingTest() {
// Arrange
RouteCollection routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
rmRequest.Stub(e => e.AppRelativeCurrentExecutionFilePath).Return("~/Home/Index");
// Act
RouteData routeData = routes.GetRouteData(rmContext);
// Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("Home",routeData.Values["controller"]);
Assert.AreEqual("Index",routeData.Values["action"]);
}
[TestMethod]
public void MoqRoutingTest() {
// Arrange
RouteCollection routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
moqRequest.Setup(e => e.AppRelativeCurrentExecutionFilePath).Returns("~/Home/Index");
// Act
RouteData routeData = routes.GetRouteData(moqContext.Object);
// Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("Home", routeData.Values["controller"]);
Assert.AreEqual("Index", routeData.Values["action"]);
}
#endregion

Sorry, but I included regions because we'll have more unit tests.
Forms and QueryStrings
While we could test to see if this data was submitted successfully through the controller, a better
test is to make sure our request returns the right form data and query strings.

I've made another alteration to the SetupTests method at the top to accommodate our form/querystring values (in
bold).
private NameValueCollection formValues;
[TestInitialize]
public void SetupTests() {
// Setup Rhino Mocks
rmContext = MockRepository.GenerateMock<HttpContextBase>();
rmRequest = MockRepository.GenerateMock<HttpRequestBase>();
rmContext.Stub(x => x.Request).Return(rmRequest);

Page 9 of 12

// Setup Moq
moqContext = new Mock<HttpContextBase>();
moqRequest = new Mock<HttpRequestBase>();
moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
// Create a "fake" form
formValues = new NameValueCollection
{
{ "FirstName", "Jonathan" },
{ "LastName", "Danylko" }
};

While it may seem like a simple task to place the data and retrieve it back out, it confirms that we have our
HttpContext and HttpRequest mocks objects setup properly.
#region Forms Tests
[TestMethod]
public void RhinoMocksFormsTest() {
// Arrange
rmRequest.Stub(r => r.Form).Return(formValues);
// Act
var forms = rmContext.Request.Form;
// Assert
Assert.IsNotNull(forms);
Assert.AreEqual("Jonathan", forms["FirstName"]);
Assert.AreEqual("Danylko", forms["LastName"]);
}
[TestMethod]
public void MoqFormsTest() {
// Arrange
moqRequest.Setup(r => r.Form).Returns(formValues);
// Act
var forms = moqContext.Object.Request.Form;
// Assert
Assert.IsNotNull(forms);
Assert.AreEqual("Jonathan", forms["FirstName"]);
Assert.AreEqual("Danylko", forms["LastName"]);
}
#endregion
#region QueryString Tests
[TestMethod]
public void RhinoMocksQueryStringTest() {
// Arrange
rmRequest.Stub(r => r.QueryString).Return(formValues);
// Act
var queryString = rmContext.Request.QueryString;
// Assert
Assert.IsNotNull(queryString);
Assert.AreEqual("Jonathan", queryString["FirstName"]);
Assert.AreEqual("Danylko", queryString["LastName"]);
}
[TestMethod]
public void MoqQueryStringTest() {
// Arrange
moqRequest.Setup(r => r.QueryString).Returns(formValues);
// Act
var queryString = moqContext.Object.Request.QueryString;
// Assert
Assert.IsNotNull(queryString);
Assert.AreEqual("Jonathan", queryString["FirstName"]);
Assert.AreEqual("Danylko", queryString["LastName"]);
}
#endregion

BTW, this would also work with cookies.


Server Variables

Server Variables can be manipulated as well using a NameValueCollection.


Why would you want to test Server Variables?

Page 10 of 12

If you want to test your code to display something if someone came from Google with a query search, you can
display a message saying "Coming From Google? Thanks for visiting. Check out these links."
You would definitely want to Unit Test that functionality. Of course, you could use the Request.UrlReferrer, but
I'm trying to prove a point that you could unit test Server Variables. ;-)
#region Server Variable Tests
[TestMethod]
public void RhinoMocksServerVariableTest() {
// Arrange
rmRequest.Stub(x => x.Url).Return(new Uri("http://localhost"));
rmRequest.Stub(x => x.ServerVariables).Return(new NameValueCollection
{
{"SERVER_NAME", "localhost"}, {"SCRIPT_NAME", "localhost"},
{"SERVER_PORT", "80"},
{"REMOTE_ADDR", "127.0.0.1"},
{"REMOTE_HOST", "127.0.0.1"}
});
// Act
var variables = rmContext.Request.ServerVariables;
// Assert
Assert.IsNotNull(variables);
Assert.AreEqual("localhost", variables["SERVER_NAME"]);
}
[TestMethod]
public void MoqServerVariableTest(){
// Arrange
moqRequest.Setup(x => x.Url).Returns(new Uri("http://localhost"));
moqRequest.Setup(x => x.ServerVariables).Returns(new NameValueCollection
{
{"SERVER_NAME", "localhost"}, {"SCRIPT_NAME", "localhost"},
{"SERVER_PORT", "80"}, {"REMOTE_ADDR", "127.0.0.1"}, {
"REMOTE_HOST", "127.0.0.1"}
});
// Act
var variables = moqContext.Object.Request.ServerVariables;
// Assert
Assert.IsNotNull(variables);
Assert.AreEqual("localhost", variables["SERVER_NAME"]);
}
#endregion

ControllerContext

Finally, we will create a mock ControllerContext. If you are doing any kind of controller unit tests, this is an
absolute must.
For those new to unit testing ASP.NET MVC, you can't create a controller without a ControllerContext. It passes
in the HttpContext (for the url information), the Routing Data (to compare with the url), and the actual controller
for executing a method.
Once we have all three of those parameters, we can mock a ControllerContext.

#region ControllerContext
[TestMethod]
public void RhinoMocksControllerContextTest() {
// Arrange
var controller = new SubscribeController();
var context = new ControllerContext(rmContext, new RouteData(), controller);
controller.ControllerContext = context;
var parameters = new SubscribeParameter();
// Act
var result = controller.SignUp(parameters) as ProcessResult<SubscribeParameter>;
// Use ViewResult here for your results. This is a specific ActionResult I built.
// Assert
Assert.IsNotNull(result);
}
[TestMethod]
public void MoqControllerContextTest() {
// Arrange
var controller = new SubscribeController();

Page 11 of 12

controller.ControllerContext = new ControllerContext(moqContext.Object, new RouteData(), controller);


var parameters = new SubscribeParameter();
// Act
var result = controller.SignUp(parameters) as ProcessResult<SubscribeParameter>;
// Use ViewResult here for your results. This is a specific ActionResult I built.
// Assert
Assert.IsNotNull(result);

}
#endregion

All we needed was a mocked HttpContext and a single controller to make sure everything worked for your unit
test to pass.
The ProcessResult returned is a custom ActionResult I built. For the simple ViewResult, your unit test could check
to see if you have a valid ViewModel returning from the ViewResult.
Conclusion

I hope this post simplifies the mocking of the HttpContext using either Moq or RhinoMocks. Once you see the
pattern, it gets easier and easier to write unit tests.
The amount of unit tests for ASP.NET MVC can be staggering, but you can easily mock up any object for any test.
The more you write, the better you'll become.
You just need to stick with it to write quality code.
Did I miss an MVC hook that I didn't cover in this post? Make me aware of it! Let me know in the comments
below.

Page 12 of 12

You might also like