Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Unit Testing with Unity Application Block

3.86/5 (5 votes)
12 Feb 2011CPOL4 min read 62.7K   843  
Using Unity Application block to perform unit testing

Introduction

This article would discuss how to use Unity Application Block for unit testing. Unity Application Block provides a dependency injection container. It is available as part of Microsoft Enterprise Library and separately as well. It can be downloaded from here.

Background

Unit testing most commonly needs a test program and mock objects / stubs. Test program would be the test projects provided by Visual Studio. Now, one does not need to write code for creating Unit under test and initialize it with respective mock or stubs to be able to do testing in isolation. This can be accomplished through Unity and one can just concentrate on writing better tests for the unit under test.

Unit Testing

Automating unit testing allows developers and testers a better and quick way to test their code for logical errors. Once created, running these tests as the code changes and adding more tests makes sure that the developer working on it has not introduced any defects.

Following are some of these guidelines to keep in mind while writing unit tests:

  • Single Condition Tests.
  • Test concerns separately, for example, there should be separate tests for Business and Data access layers.
  • Minimize test overlap.
  • Defect Localization, keeping unit tests small, in case of a defect, it will be easy to locate it based on the failing test.
  • Keep Tests Independent, Fresh Fixture strategy would help.
  • Self checking Tests, using Built-in/Custom Assertions.
  • Purpose of the test should be very clear.
  • Minimize un-testable code.
  • Keep test logic out of production.
  • Tests should be repeatable.
  • Write the unit test first. This is optional depending on if test-driven development or test-first development is used.

Also, some of the guidelines and patterns for organizing unit test such as Testcase class per Feature, Testcase class per Fixture can be considered.

Unity Application Block

Unity Application Block provides a dependency injection container. Dependency Injection is a pattern allowing loose coupling on the principle of separating behavior from dependency resolution. Unity is a lightweight and extensible dependency injection container that supports injection through constructor, property and method call. It can help in de-coupling, simplifying design and testing of the application.

Design

Design1.JPG

Layered architecture simplifies automated testing, as simple as 3-Tier architecture would do. In the above diagram, I have shown ICustomerFacade, ICustomerManager implemented by CustomerFacade, CustomerManager components respectively. This is Interface-based programming; interfaces provide contract or specification for implementation, all the classes implementation should conform to the contract. We need to have interface at each component. In terms of dependency injection, a dependent consumer.

Using the Code

Before we start on the steps for creating and configuring unity, it’s required to have Enterprise Library 5.0 or Microsoft Unity 2.0 installed.

To begin with, we take an example of the business facade class CustomerFacade, this is how it looks:

C#
public class CustomerFacade : ICustomerFacade
{
    [Dependency]
    public ICustomerManager CustomerManager { get; set; }

    #region ICustomerFacade Members

    public long CreateCustomer(Customer customer)
    {
        try
        {
            return CustomerManager.CreateCustomer(customer);
        }
        catch (Exception e)
        {
            throw new BusinessException("BusinessException Occurred", e);
        }
    }

    #endregion
}   

For the sake of simplicity, I have taken a vanilla example.

The properties to be resolved using unity should be marked with DependencyAttribute. In the above code, CustomerManager property has this attribute.

CustomerFacade implements interface ICustomerFacade, there by separating behavior from dependency:

C#
public interface ICustomerFacade
{
    long CreateCustomer(Customer customer);
}

Now, we will see how we can test CustomerFacade with the help of Unity Application block:

Step 1: Create Test project and add references

  1. Add a test project to the solution in Visual Studio.
  2. Add references to Microsoft.Practices.Unity, Microsoft.Practices.Unity.Configuration, System.Configuration.

Step 2: Add Test class

  1. Add a test class to the test project created in Step 1.
  2. Import namespaces .Practices.Unity, Microsoft.Practices.Unity.Configuration, System.Configuration.

Step 1 and Step 2 can be automated using Visual Studio 2008 Professional

  1. Right click on the method and choose Create Unit Tests…
  2. In the dialog box, select the methods to be included for automatic Test class and method generation.
  3. Select an Existing or New Test project
  4. Click Ok

Step 3: Add an App.config file to the test project created in Step 1.

Step 4: Setup the Unity Configuration part of the App.config file created in Step 3:

XML
<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>
      <section name="unity" 
	type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, 
	Microsoft.Practices.Unity.Configuration"/>
  </configSections>

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"
<assembly name="UnitTestingWithUnity" />
<assembly name="UnitTestingWithUnity.Test" />
<namespace name="UnitTestingWithUnity.BusinessFacade" />
<namespace name="UnitTestingWithUnity.Business" />
<namespace name="UnitTestingWithUnity.Data" />
<namespace name="UnitTestingWithUnity.Test.Mock" />

<container>
<register type="ICustomerManager" mapTo="MockCustomerManager" />
<register type="ICustomerDataAccess" mapTo="MockCustomerDataAccess" />
</container>

</unity>
</configuration>       

Understanding the configuration file:

  1. Add the UnityConfigurationSection reference to your configuration file.
  2. Add all the assembly and namespaces required to resolve the interface and the implementation classes in the configuration.
  3. MockCustomerManager class implements interface ICustomerManager.
  4. Register the interfaces to be resolved using the container with the respective map to class.

Step 5: Writing your test:

TestInitilize method should initialize the unity container to load the unity configuration created in the previous step.

C#
private IunityContainer unityContainer;

[TestInitialize()]
public void MyTestInitialize()
{
    unityContainer = new UnityContainer();
    unityContainer.LoadConfiguration();
}

Unity container can be initialized without using the configuration files as well. Instead of LoadConfiguration, we should use RegisterType method on unity container.

C#
unityContainer.RegisterType<ICustomerManager, CustomerManager >();
unityContainer.RegisterType<ICustomerDataAccess, CustomerDataAccess>();

In the test method, we will use the unity container we just created to resolve the CustomerFacade class.

C#
/// <summary>
///A test for CreateCustomer
///</summary>
[TestMethod()]
public void CreateCustomerTest2()
{
ICustomerFacade target = new CustomerFacade();
target = unityContainer.BuildUp<ICustomerFacade>(target);
Customer customer = new Customer{Name="Test 1", Address = "Test Address 1" };
long custId = target.CreateCustomer(customer);Assert.AreEqual(custId, 1);
}

For Unity to resolve all the dependencies, we should use the dependency injection container provided by Unity to construct and initialize objects. It can be done in 2 ways:

Create the object with new operator, and then use BuildUp method on unity container to resolve all the dependencies:

C#
ICustomerFacade target = new CustomerFacade();
target = unityContainer.BuildUp<ICustomerFacade>(target); 

Alternatively, use Resolve generic method to create and resolve dependencies in one go:

C#
ICustomerFacade target = unityContainer.Resolve<CustomerFacade>(); 

Step 6: Execute the Test just created.

That’s about it.

References

History

  • 12th February, 2011: Initial post

License

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