There is no doubt that in recent years there has been an increased focus on unit testing our code before we throw it over the fence. Despite this increased focus we still see piles of code out in the field that is virtually untestable despite it exhibiting several other positive characteristics. So what is it that makes it so hard to write a piece of code that is easily unit testable?

Ironically I think that a lot of the blame falls on the unit testing gurus who produce frameworks which are supposed to guide us into making testable code. I’m talking about inversion of control frameworks which implement various flavors of the dependency injection pattern or the service locator pattern. While the frameworks themselves are powerful they are somewhat unapproachable to your average development team member which is having a hard enough time coming to terms with the humble DataSet – don’t laugh, every team has at least one!

Rather than focus on a set framework I think we should make one simple change to our collective coding styles. Lets take a look at the following piece of code that you might find any your typical layered business application:

public class CustomerBusinessComponent

{

    public Customer Find(string customerID)

    {

        CustomerDataComponent data = new CustomerDataComponent();

        Customer customer = data.Load(customerID);

        return customer;

    }

In this example we can see that the higher caller would invoke Find and this business component would then load the customer based on the customer ID that was passed in. Hopefully a business logic component would justify its existence by doing more than this, but it is fine for the purposes of this demonstration. The problem with this code is that it is tightly coupled with the layer below, which probably means it is tightly coupled (ultimately) to the database.

Microsoft product teams have a saying about not taking any dependencies when you ship, but we can understand where the SQL and .NET teams went so wrong – its so easy to do! We do it with every piece of code that we write! In order to make the code above more unit testable we should really extract the hard dependency on CustomerDataComponent so that we can provide our own implementation, here is a quick and dirty example that gets the job done.

public class CustomerBusinessComponent

{

    private CustomerDataComponent m_CustomerDataComponent = new CustomerDataComponent();

 

    public CustomerDataComponent DataComponent

    {

        get { return this.m_CustomerDataComponent; }

        set { this.m_CustomerDataComponent = value; }

    }

 

    public Customer Find(string customerID)

    {

        Customer customer = this.DataComponent.Load(customerID);

        return customer;

    }

}

The beauty here is that our test code can now provide its own data component implementation:

public class TestCustomerDataComponent : CustomerDataComponent

{

    public override Customer Load(string customerID);

    {

        Customer cust = new Customer();

        cust.ID = "DUMMY";

        return cust

    }

}

 

[TestClass()]

public class CustomerBusinessComponentTests

{

    [TestMethod()]

    public void SunnyWeatherFindTest() // This is a Jackism.

    {

        CustomerBusinessComponent businessComponent = new CustomerBusinessComponent();

        businessComponent.DataComponent = new TestCustomerDataComponent();

        Customer customer = businessComponent.Find("DUMMY");

        Assertion.AreEqual<string>("DUMMY", customer.ID);

    }

}

There are a couple of subtle implications here. The first is that your should start defining the methods you are planning on stubbing out as virtual but you should also consider the other changes when you switch to this style of coding. First of all – lets say I instantiated my CustomerBusinessComponent, well my CustomerDataComponent would get instantiated automatically – but if I never called Find that could have potentially been wasteful. If you applied this pattern throughout your layers you could well end up with thousands of objects being instantiated just to make one simple call, so we can optimise the code to be more memory efficient (memory efficiency is more important than runtime efficiency in .NET – space is king).

public class CustomerBusinessComponent

{

    private CustomerDataComponent m_CustomerDataComponent;

 

    public CustomerDataComponent DataComponent

    {

        get

        {

            if (this.m_CustomerDataComponent == null)

            {

                this.m_CustomerDataComponent = new CustomerDataComponent();

            }

 

            return this.m_CustomerDataComponent;

        }

        set { this.m_CustomerDataComponent = value; }

    }

 

    public Customer Find(string customerID)

    {

        Customer customer = this.DataComponent.Load(customerID);

        return customer;

    }

}

Finally, there are a few things that you could do to improve this as a testing mechanism. First, you could make the test data access component take an anonymous method in its constructor which would allow the test case code to define what the return value from the dependency it is injecting. This could be useful when dealing with data driven unit tests in Visual Studio Team System or combinatorial tests in MbUnit – but that’s a topic for another technical moment!