Coding for Testability

November 20, 2005

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!

6 Responses to “Coding for Testability”

  1. Paul Stovell Says:

    Mitch,

    One issue with that code is your testing layer (and, thus, possibly your GUI layer) are able to control which DataCompoenent your business components are using. This will in turn mean your GUI will need a reference to your DAC. In a loose-layering system this may not be an issue, but if you’re a Layering Nazi this could be a problem.

    This is the style that I follow:

    public interface ICustomerBusinessComponent

    {

    public abstract Customer Find(string customerID);

    }

    public sealed class CustomerBusinessComponent

    {

    private static ICustomerBusinessComponent _current;

    public static ICustomerBusinessComponent Current

    {

    get

    {

    if (_current == null)

    {

    _current = new CustomerBusinessComponent();

    }

    return _current;

    }

    set { _current = value; }

    }

    }

    Now, to unit test it, you do need to create a seperate class:

    public class TestCustomerBusinessComponent:

    ICustomerBusinessComponent

    {

    public Customer Find(string customerID)

    {

    CustomerDataComponent cdc = new CustomerDataComponent();

    return cdc.Load(customerID);

    }

    }

    The basic idea is your test code becomes:

    [TestMethod()]

    public void SunnyWeatherFindTest()

    {

    CustomerBusinessComponent.Current = new TestCustomerBusinessComponent();

    Customer customer = CustomerBusinessComponent.Current.Find(“DUMMY”);

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

    }

    This has two benefits I can see:

    1) Calling code never assigns a DAC directly

    2) It gives you flexibility to add other business components (maybe you’ll add one that knows how to get data from XML)

    3) It results in a little less code

    One thing: I’m not sure on the convention of having ICustomerBusinessComponent and a CustomerBusinessComponent class that doesn’t implement the interface, but rather called out for classes that do implement it.

    But I lie. This isn’t actually how I do it. Rather, I go a step further, and eliminate the extra CustomerBusinessComponent class:

    My data layer has a DataSource class. A DataSource looks like this:

    public abstract class DataSource

    {

    public static DataSource Current

    {

    get

    {

    if (_current == null)

    {

    // By default, I assume all data comes from SQL

    _current = new SqlDataSource();

    }

    return _current;

    }

    set { _current = value; }

    }

    public abstract CustomerDataComponent GetCustomerComponent();

    }

    When a new data source (SQL Server or a special data source for unit testing) comes along, I create a new class implementing DataSource. A SqlDataSource’s implementation of GetCustomerComponent() might return a SqlCustomerDataComponent, while a TestDataSource might return a TestCustomerDataComponent, and both of these will return whatever data they need to.

    My business layer has a “BusinessSource” where you chose which data source to set.

    public abstract class BusinessSource

    {

    enum DataProvider

    {

    SQL,

    Testing

    }

    public void SetCurrent(DataProvider p)

    {

    if (p == DataProvider.SQL)

    {

    DataSource.Current = new SqlDataSource(“connection string?”);

    }

    else if (p == DataProvider.Testing)

    {

    DataSource.Current = new TestDataSource();

    }

    }

    }

    Now, my business layer need only go:

    public class CustomerBusinessComponent

    {

    public Customer Find(string customerID)

    {

    CustomerDataComponent = DataSource.Current.GetCustomerComponent();

    return cdc.Load(customerID);

    }

    }

    And whalla! To unit test:

    [TestMethod()]

    public void SunnyWeatherFindTest()

    {

    BusinessSource.SetCurrent(DataProvider.Test);

    CustomerBusinessComponent cbc = new CustomerBusinessComponent();

    Customer customer = cbc.Find(“DUMMY”);

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

    }

    This has the advantages of:

    1) You can change the entire data source just once, and in one location.

    2) Upper layers still don’t have to know about the data layer – they just assign to DataSource.Current, which is a business object.

    3) You’re only implementing the bare minimum to get a new data source.

    However, one disadvantage is in the code I showed, your “BusinessSource” needs to know which data sources are avaliable. This is a bit tightly coupled for my liking, so I create special BusinessSource classes (one for each data source) to make it looser. But they still only set DataSource.Current to the correct DataSource. I can show you the actual (working) implementation of this code if you like.

    That was a long comment; maybe I should have blogged it instead.

  2. Paul Stovell Says:

    Ooops, that code came out a little mangled. Feel free to delete that comment and see an extended version here:

    http://www.paulstovell.net/Posts/Post.aspx?postId=ed9b476d-df71-482c-b2cf-f24a97e81942

  3. Josh Twist Says:

    Hi Mitch,

    Interesting post. I’d love to hear your thoughts about stubbing out third party components.

    For example, imagine we want to write a wrapper for a third party component such that it can be replaced with a different third party component when the time suits. Lets say in this example we want to wrap log4net’s excellent logging library (but later we may want to use something else).

    How does one approach stubbing out such a library? I don’t want to present anything *log4netty* in my wrapper class as it wouldn’t be impartial anymore.

  4. Mitch Denny Says:

    Hi Josh,

    Stubbing is hard, especially with pervasive API’s like logging ones. I guess the best thing to do in that case is just produce an abstract Logger API and then do an implementation for log4net.

    However – why not just use System.Diagnostics and implement a TraceListener! :)


  5. [...] notgartner » Blog Archive » Coding for Testability [...]


Leave a Reply