Friday, October 2, 2009

Testing with Unity

I’m developing a test framework for component interaction testing. It’s a legacy application and developers did not keep testability in mind when they were designing the architecture.

One main problem is coupling, mainly efferent coupling. Let’s say we have class A. It creates class B. Class B creates class C. If we want to inject a mock or stub of B or C into the system, it’s probably impossible without code modification.

EfferentCouplingYou are lucky if you have a factory method that produces B or C. Usually they are just  local variables of a method. Sometimes you can override the virtual method containing such references, but in this case you will loose existing code.

One of the easiest methods is employing Microsoft Unity (Application Block). You can find the following definition of Unity on MSDN:

The Unity Application Block (Unity) is a lightweight, extensible dependency injection container with support for constructor, property, and method call injection. It provides developers with the following advantages:

  • It provides simplified object creation, especially for hierarchical object structures and dependencies, which simplifies application code.
  • It supports abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns.
  • It increases flexibility by deferring component configuration to the container.
  • It has a service location capability; this allows clients to store or cache the container. This is especially useful in ASP.NET Web applications where the developers can persist the container in the ASP.NET session or application.

So Unity can create objects automatically by defining just the interface of the desired class. You can freely change implementation class. E.g. you can inject a complete communication layer class (which implements a communication functionality over TCP) into the production code, and you can easily inject a mock class (which just emulates the communication) into the test framework.

An example of class registration:

myContainer.RegisterType<IMyService, CustomerService>();

An example of creating a concrete class:

IMyService myServiceInstance = myContainer.Resolve<IMyService>();
Now you can inject mock or stub classes into the testing framework without production code modifications. I think it’s a nice solution.