Introduction
I’m currently working on an ASP.NET MVC prototype that I’m going to demonstrate Unity Testing a Controller which uses Dependency Injection.
In my case, I’m using ASP.NET MVC controllers that have a dependency on certain actions. I wanted to keep the Controller as clean as possible, so I created an IAction interface. Let’s call it HomeController for now.
public class HomeController : SecuredBaseController
{
private ISearchAction searchAction;
public HomeController(ISearchAction searchAction)
{
this.searchAction = searchAction;
}
public ActionResult Home()
{
ViewData["Title"] = "Summary";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
SubmissionStatus[] submissionStatusList =
this.searchAction.GetSubmissionStatusForAuditor();
SelectList reviewStatusList = new SelectList(submissionStatusList, "Id",
"InternalDisplayName");
ViewData["ReviewStatusId"] = reviewStatusList;
CountryRegion[] countryList = this.searchAction.GetCountries();
SelectList countrySelectList = new SelectList(countryList, "Id", "Name");
ViewData["CountryId"] = countrySelectList;
Program[] programs = this.searchAction.GetFilteredProgramList();
SelectList programSelectList = new SelectList(programs, "Id", "Name");
ViewData["ProgramId"] = programSelectList;
Item[] activityTypes = this.searchAction.GetActivityTypesForAuditor();
SelectList activityTypesSelectList = new SelectList(activityTypes, "Id", "Name");
ViewData["ActivityTypeId"] = activityTypesSelectList;
return View("ViewPoeSubmissions");
}
You can see that we have a search page that calls a Search Action interface with all the code contained in a SearchAction class. The SearchAction class is in a, you guessed it.. Unity Container. I won’t go into the factory class that creates the Unity Container right now. I’ll write another article on that item, but for now, the Unity Container is actually created on Application_Start() and looks something like: ControllerBuilder.Current.SetControllerFactory(UnityContainers.Instance.Resolve<IControllerFactory>());.
The Solution
How do we test this? As I mentioned above, the Unity Container is created on Application_Start() for our website, but since the controller takes an Interface, I can mock that up using the Repository pattern in the Unit Tests.
Here is what the SearchAction class looks like:
public class SearchAction : IPoeSearchAction
{
private ITaxonomyModel taxonomyModel;
private IRequestModel requestModel;
{
this.taxonomyModel = taxonomyModel;
this.requestModel = requestModel;
}
Notice that the constructor for SearchAction takes two Interfaces: ItaxonomyModel and IrequestModel.
The GetCountries() method of the SearchAction class looks like this:
public CountryRegion[] GetCountries()
{
return this.taxonomyModel.GetCountries();
}
It’s actually the TaxonomyModel class that calls the Web Service and takes care of the GetCountries() code, so I can create a class called TestTaxonomyModel that implements the ItaxonomyModel interface, and in that test class, I can put mock code in the GetCountries method that will return a subset of the test data.
The RequestModel class works the same way.
public ClaimSearchResult Search(FormCollection form)
{
ClaimSearchCriteria criteria = this.CreateSearchCriteria(form);
return this.requestModel.SearchClaims(searchCriteria);
}
I can create a class called TestRequestModel that implements the IRequestModel interface, and put logic to return test data based upon the search criterion passed in.
Here is what my Unit Test looks like. First, I initialize a Unity Container with test data:
private IServiceLocator serviceLocator;
private IUnityContainer unityContainer;
TestInitialize]
public void InitializeTests()
{
this.unityContainer = new UnityContainer()
.RegisterType<IController, HomeController>()
.RegisterType<ISearchAction, SearchAction>();
this.unityContainer.Configure<InjectedMembers>()
.ConfigureInjectionFor<SearchAction>(new InjectionConstructor(new object[] {
new TestTaxonomyModel(), new TestRequestModel() }))
.ConfigureInjectionFor<HomeController>(new InjectionConstructor(
this.unityContainer.Resolve<ISearchAction>()));
unityContainer.Resolve<IController>();
this.serviceLocator = new MyServiceLocator(this.unityContainer);
}
[TestMethod]
public void SearchTest()
{
var homeController = new HomeController(
this.serviceLocator.GetInstance<SearchAction>());
FormCollection form = new FormCollection();
form["ProgramId"] = "3";
form["ActivityId"] = "8";
form["CountryId"] = "33";
form["Filter"] = "3";
form["Region"] = "Foo";
searchController.Search(form);
}
There, you can see that we call the Search method on the search controller, passing it the form we created, and the code will be applied against our test controllers.
Read more about this at my website.