Tag Archive: unit testing


Breaking Unit Tests

Breaking Unit Tests

How to create an automated unit test for your controller in ASP.NET MVC

In this example, we will create an automated unit test for a controller action. This is a great tool for isolating issues with javascript and ajax calls by verifying the presentation layer (i.e. the page) is actually getting the correct info from the controller and lower layers.
Don’t make your base controller decide if the site menu should appear on a group of pages, let a master page decide if the menu should appear on a group of pages

Make sure your login pages (i.e. the aspx views in YourSolution/Views/Account) use Logon.Master instead of Site.Master. Your login pages will not be showing the site map menu, so you’ll need to leave out the SiteMap line from your Logon.Master entirely.

Create the test for the controller

As long as you have a separation of concerns in your application, you can easily create a controller test like the example below which uses the Arrange-Act-Assert pattern. Notice that our FillDDL action returns a JsonResult (which would be consumed by an ajax call such from a jqgrid or jq getjson). In the test, the JsonResult is verified to contain the expected data.

[Test]
public void FillDDL_ReturnsCorrectJsonResult()
{
    // *** ARRANGE ***
    // create a mock of the dependencies
    IMyBLL mockMyBLL = MockRepository.GenerateMock<imybll>();
    IMyOtherBLL mockMyOtherBLL = MockRepository.GenerateMock<imyotherbll>();
    DDL test = new DDL {Disp = "XXX", Value = "111"};
    List<ddl> testList = new List<ddl> {test};
    mockMyBLL.Stub(c => c.GetList()).Return(testList);
    
    // *** ACT ***
    // get the concrete class that will be tested; inject all the mocks into the concrete class
    // Note: if a dependency can't be injected thru a constructor, you can use this:
    ObjectFactory.Inject(typeof(IMyOtherBLL), mockMyOtherBLL);
    MyController controller = new MyController(mockMyBLL);
    // run the test method
    JsonResult resultJson = controller.FillDDL();

    // *** ASSERT ***
    // verify test results
    List<ddl> resultList = (List<ddl>) resultJson.Data;
    Assert.AreEqual(test.Disp, resultList[0].Disp);
    Assert.AreEqual(test.Value, resultList[0].Value);
}

Here’s an easier way to do dependency injection and build controllers without parameterless constructors in ASP.NET MVC. If you want cleaner code and easier unit tests for your controllers and BLLs, follow the instructions below to use top-down dependency injection using Structure Map.

1. Replace the default System.Web.Mvc.ControllerBuilder with a StructureMap controller factory: First, create a new class called StructureMapControllerFactory in the presentation layer.

using System;
using System.Diagnostics;
using System.Web.Mvc;
using StructureMap;
namespace MyWebApp
{
/// <summary>
/// Used in Global.asax's Application_Start method to replace the default System.Web.Mvc.ControllerBuilder with this StructureMap controller factory.
/// </summary>
public class StructureMapControllerFactory : DefaultControllerFactory
{
/// <summary>
/// Use StructureMap to construct the controller and all its dependencies.
/// </summary>
/// <param name="controllerType">Type of the controller.</param>
/// <returns>A reference to the controller.</returns>
protected override IController GetControllerInstance(Type controllerType)
{
if (controllerType == null)
return null;
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
}

2. Then use the new StructureMapControllerFactory in Global.asax.cs’s Application_Start method. Add this line right below the Bootstrapper.Bootstrap() call:

ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());

3. You don’t need a parameterless constructor for your controllers anymore. Make sure you pass in any dependent blls/etc. in all of your controllers’ constructors (i.e. don’t use ObjectFactory). Like this:

private readonly IMyBLL myBLL;public MyController(IMyBLL myBLL){this.myBLL = myBLL;}

4. Make sure you pass in dependent blls/dals /etc. in all of your BLLs’ constructors (i.e. don’t use ObjectFactory). Like this:

private readonly IMyDAL myDAL;
public MyBLL(IMyDAL myDAL){this.myDAL = myDAL;}
© 2017 Robert Corvus