Click here to Skip to main content
15,884,472 members
Articles / Web Development / ASP.NET

Using a Unity Container with Dependency Injection for Unit Testing with ASP.NET MVC

Rate me:
Please Sign up or sign in to vote.
4.00/5 (2 votes)
5 Feb 2009CPOL2 min read 45.6K   18   3
Using a Unity Container or Service Locator with Dependency Injection for Unit Testing.

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.

C#
/// <summary> 
/// HomeController class. 
/// </summary> 
public class HomeController : SecuredBaseController 
{ 
    /// <summary> 
    /// Search Action Interface. 
    /// </summary> 
    private ISearchAction searchAction; 
    /// <summary> 
    /// Constructor for Home Controller. 
    /// </summary> 
    /// <param name="searchAction">Home page search action.</param> 
    public HomeController(ISearchAction searchAction) 
    { 
        this.searchAction = searchAction; 
    } 
    /// <summary> 
    /// Load view Index. 
    /// </summary> 
    /// <returns>Action Result.</returns> 
    public ActionResult Home() 
    { 
        ViewData["Title"] = "Summary"; 
        ViewData["Message"] = "Welcome to ASP.NET MVC!"; 
        //// get valid review status 
        SubmissionStatus[] submissionStatusList =
            this.searchAction.GetSubmissionStatusForAuditor(); 
        SelectList reviewStatusList = new SelectList(submissionStatusList, "Id",
            "InternalDisplayName"); 
        ViewData["ReviewStatusId"] = reviewStatusList; 
        //// primary countries 
        CountryRegion[] countryList = this.searchAction.GetCountries(); 
        SelectList countrySelectList = new SelectList(countryList, "Id", "Name"); 
        ViewData["CountryId"] = countrySelectList; 
        //// get programs 
        Program[] programs = this.searchAction.GetFilteredProgramList(); 
        SelectList programSelectList = new SelectList(programs, "Id", "Name"); 
        ViewData["ProgramId"] = programSelectList; 
        //// get activity types 
        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:

C#
/// <summary> 
/// Search action class for the controller. 
/// </summary> 
public class SearchAction : IPoeSearchAction 
{ 
    /// <summary> 
    /// Taxonomy model interface. 
    /// </summary> 
    private ITaxonomyModel taxonomyModel; 
    /// <summary> 
    /// Activity request model interface. 
    /// </summary> 
    private IRequestModel requestModel; 
    /// <summary> 
    /// Search Action. 
    /// </summary> 
    /// <param name="taxonomyModel">Taxonomy Model Interface.</param> 
    /// <param name="requestModel">Request Model Interface.</param>
    /// public SearchAction(ITaxonomyModel taxonomyModel, 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:

C#
/// <summary> 
/// Get list of primary countries. 
/// </summary> 
/// <returns>Country region collection.</returns> 
public CountryRegion[] GetCountries() 
{ 
    // Grab the Instance from Activity Request Process. 
    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.

C#
/// <summary> 
/// Search for a Claim. 
/// </summary> 
/// <param name="form">Form Collection.</param> 
/// <returns>Activity Based Claim Search Result.</returns> 
public ClaimSearchResult Search(FormCollection form) 
{ 
    /// Create some search criteria from the form data. 
    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:

C#
/// <summary> 
/// Internal chip service locator. 
/// </summary> 
private IServiceLocator serviceLocator; 
/// <summary> 
/// Unity container. 
/// </summary> 
private IUnityContainer unityContainer; 
/// Initialize tests. 
/// </summary> 
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); 
}
/// <summary> 
/// Search test method. 
/// </summary> 
[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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Microsoft
United States United States
Chris Aloia lives in the Seattle area and works as a Senior Software Development Engineer for Microsoft Corporation.

Comments and Discussions

 
QuestionService Locator Pin
Quarterback1619-Feb-15 17:55
Quarterback1619-Feb-15 17:55 
AnswerRe: Service Locator Pin
jorgegarmilla17-Apr-15 2:59
professionaljorgegarmilla17-Apr-15 2:59 
GeneralRe: Service Locator Pin
Johannes Rossouw13-Jul-15 0:12
Johannes Rossouw13-Jul-15 0:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.