Tuesday, April 13, 2010
When we are unit testing a piece of code, sometimes there are modules or even systems that we need to rely on outside the scope of the test. It is usually very difficult or expensive to spin up these large pieces just to test one small piece. Even attempting to do this can really slow down the execution of the tests, and that becomes a problem of its own. When possible, we'd like to separate the implementation from the caller's execution so that the control is really in the called module doing the work. This is the "Inversion of Control" or IoC principle, as it's often referred.

Dependency Injection is one mechanism where we can design our code in this way. Dependency injection [DI] is like "injecting" a small bit of test-controlled code into the main-line execution space while the test is running. The test can control the specific execution of the "dependency" code, and cause it to behave in a specific way so as to elicit a specific behavior from the mainline code under test.

My favorite mechanism to accomplish DI is to refactor code under test, extracting the logic of the dependency into a class that implements an interface. Then, we can create a test mechanism that implements the interface and behaves in the way that the test can control. We then replace the mainline "real" code with the test version at test time, bypassing the dependency and allowing us to remain focused on the code under test.
We can implement this with simple classes, or with Mock objects. The mock object frameworks out there today are quite robust and relatively easy to use, given an interface to implement for the dependency class. Rhino Mocks and Moq are some examples of frameworks that can be used for this type of test. Here is a simple example of some code under test:

using System;

namespace DIexample
{
public class ClassUnderTest
{
internal
IDependOnMe limit = new Limiter();

public int HasDependencyOnExternalClass(int value)
{
if (value < 0)
{
return limit.LogicFunction(value);
}
else { return value;
}
}
}

interface IDependOnMe
{
int LogicFunction(int value);
}

public class Limiter : IDependOnMe
{
public int LogicFunction(int value)
{
if (value < -10)
{
return value;
}
else { return -10;
}
}
}
}


At test time, we can replace the internal variable "limit" with a test-created instance of an object that implements the "DependOnMe" interface, and behaves in a specific way (like just returning the value perhaps). The variable "limit" is declared as "internal" scope, because we want the test code to be able to access it and replace its "real" object instance with a test-specific version. I keep the test assembly separate from the mainline code. However, I don't like the idea of making these mechanisms public unless they need to be, so instead in the mainline code, I use the internals visible to assembly attribute like this:

using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("TestAssembly")]

This allows all "internal" scoped methods to be accessed by the test assembly, and keeps all the test code out of the mainline code, and maintains at least a level of security that being public doesn't offer.

Mock frameworks can be a big help in this type of DI testing. Rhino Mocks is here: http://ayende.com/projects/rhino-mocks.aspx it's a good free framework and fully featured. I've not used it but heard good things about MOQ: http://code.google.com/p/moq/

Remember to keep the execution isolated from the implementation whenever possible, and it will make unit testing much easier.
Tuesday, April 13, 2010 7:41:03 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  |  Trackback
Comments are closed.
© Copyright 2012, John E. Boal