Test Helper

The TestHelper library allows simpler unit testing on MVC.Net controllers than can be accomplished through standard mocking and subclassing. It is designed to reduce the amount of work required to test controllers, and therefore should be used by your test projects but not in your web server project.

General Concepts

One of the major advantages of the new MVC.Net framework is the ease with which it can be tested. While this is generally true, there are a number of areas where testing the framework becomes difficult to do. The TestHelper assists by providing a Controller Factory that creates controllers with internal data members correctly initialized. These include:
  • HttpContext
  • HttpRequest
  • HttpResponse
  • HttpSession
  • Form
  • TempData
  • QueryString
  • ApplicationPath
  • PathInfo

It also provides a way to determine what parameters were passed to RenderView and RedirectToAction.

Examples

More examples can be found in the Samples directory of the MVC Contrib project. In that directory is a project for MvcContrib.TestHelper.Sample which contains a very simple MVC.Net project and Test. There are a number of tests in the test project which detail how to use the Test Helper. A couple of them are included below.

Testing data from RenderView method call

        [Test]
        public void ListControllerSelectsListView()
        {
            ActionResult result = controller.List();
            result.AssertViewRendered().ForView("List");
        }

Testing data from RedirectToAction method call

        [Test]
        public void AddFormStarShouldRedirectToList()
        {
            StarsController controller = new StarsController();
            ActionResult result = controller.AddFormStar();
            result.AssertActionRedirect().ToAction("List");
        }

Testing data from Form and Session variables

        [Test]
        public void AddSessionStarShouldSaveFormToSession()
        {
            TestControllerBuilder builder = new TestControllerBuilder();
            StarsController controller = new StarsController();
            builder.InitializeController(controller);

//note that this is assigned before the controller action. This simulates the server filling out the form data from the request
            builder.Form["NewStarName"] = "alpha c";


//this assumes that AddSessionStar takes the form data and adds it to the session
            controller.AddSessionStar();

            Assert.AreEqual("alpha c", controller.HttpContext.Session["NewStarName"]);
        }

Routes

Testing routes

see MVCContrib.UnitTests\TestHelper\RoutesTest.cs

using System.Web.Mvc;
using System.Web.Routing;
using NUnit.Framework;

namespace MVCContrib.Application.UnitTests.TestHelper
{
    /// <summary>
    /// Summary description for UserRoutesTest
    /// </summary>
    [TestFixture]
    public class UserRoutesTest
    {
        [TestFixtureSetUp]
        public void Setup()
        {
            var routes = RouteTable.Routes;
            routes.Clear();
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}",                                         // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
                );

        }

        [Test]
        public void homeIndex()
        {
            "~/user"
                .ShouldMapTo<HomeController>(action => action.Index());
        }


        [Test]
        public void HomeShow()
        {
                         "~/home"
                           .WithMethod(HttpVerbs.Put)
                           .ShouldMapTo<HomeController>(action => action.Index());
        }

    }
}

Last edited Nov 5, 2010 at 7:51 PM by erichexter, version 16

Comments

MasterZZZZ Nov 29, 2012 at 3:53 PM 
Hi, I imported mvcContrib but I get the can't resolve ShouldMapTo

MGalindez Dec 6, 2011 at 2:38 PM 
I was wondering if the TestHelper should set an HttpRequest, because I need to test an action that acts in different ways whether is a Post or Get http request. I solve it this way but i dont think this is the best one:

Mock<RequestContext> request = new Mock<RequestContext>();
request.Setup(r => r.HttpContext.Request.HttpMethod).Returns(httpAccion);
controller.ControllerContext = new ControllerContext(request.Object, controller);

Is there a better way? if it's not, it would be a good idea to make it simpler.
Thanks

PatriceCalve Sep 24, 2010 at 12:32 AM 
Please add the following:

Note: If you can't see "AssertViewRendered()", "AssertActionRedirect()", make sure you you import the MvcContrib.TestHelper namespace (using in C#, import in VB.Net)

TestDrivenDev Mar 15, 2010 at 12:07 AM 
As somebody completely new to MVCContrib and eager to learn, the above examples seem rather obscure. "AddSessionStarShouldSaveFormToSession()" leaves me wondering what exactly we're trying to assert. I also find the language confusing; e.g.

"simulates the server filling out the form data from the request" - model binding?

"this assumes that AddSessionStar takes the form data and adds it to the session"

Who assumes [..]? Do you mean that the AddSessionStar method assumes that AddSessionStar takes the form data and adds it to the session? Do you mean, more simply, that "AddSessionStar adds form data to the session"? I find it confusing. I'll have a look at the samples project - maybe it's just me. :)

JeremyS Nov 6, 2009 at 7:34 AM 
@HigorRamos

ForView allows you to assert that a view with a particular has been rendered.

If you have further questions, please use the mailing list (http://groups.google.com/group/mvccontrib-discuss) - these wiki comments are not intended for providing support and are not monitored.

HigorRamos Nov 5, 2009 at 9:21 PM 
Hey people, sorry but I didn't get the point. what does this ForView do?

JeremyS Jun 10, 2009 at 10:50 AM 
Fixed, thanks.

cathal_mchale Jun 10, 2009 at 9:46 AM 
FYI:

Above
>>result.AssertRenderedView().ForView("List");

Should read
result.AssertViewRendered().ForView("List");

;-)

erichexter Mar 4, 2009 at 7:35 PM 
Moq supports AutoMocking so you should not need the control builder if you are using Moq.

nkirkes Dec 19, 2008 at 6:56 PM 
Is the TestControllerBuilder tied to RhinoMocks or can any other mock library be used? I'd like to use Moq (and do so to mock out my repository), but the TestControllerBuilder is throwing an error stating it can't find the Rhino Mocks assembly.