Tom 10:14, 14 September 2009

This is the second posting in the WEWLC-series.

 

Other posts are:

I can't run this method in a test harness

I don't have much time and I have to change it

Assumptions on the reader

 

 

What to do if the system under test is a nasty legacy class that seems impossible to get under test? There are various techniques that can help you with this, let get started with "the case of the irritating parameter".

 

The case of the irritating parameter

When you have a SUT that takes complex objects into it's constructor you can easily circumvent the situation by applying Extract interface on the bothering classes.

After you have created the necessary interfaces you can utilize Rhino Mocks to generate replacement instances (mocks) of the required classes. Rhino Mocks will actually create an proxy instance for the class. Conveniently, you can then set expectations & outcomes on these mocks. So without an actual implementation you fake the system into believing it is dealing with actual classes.

Let have a look on how this works:

 

public class CreditValidator
{
    readonly IDbConnection connection;
    readonly ICreditMaster creditMaster;

    public CreditValidator(IDbConnection connection, ICreditMaster creditMaster)
    {
        this.connection = connection;
        this.creditMaster = creditMaster;
    }
}

public class CreditMaster: ICreditMaster
{
    public CreditInformation GetCreditInformation(Customer customer)
    {
        throw new NotImplementedException();
    }
}

public interface ICreditMaster
{
    CreditInformation GetCreditInformation(Customer customer);
}

First off we create an interface for the CreditMaster class. Once that is done we can start writing the test ask the Rhino MockRepository for an instance of both IDbConnection and ICreditMaster.

 

[TestFixture]
public class CreditValidatorTests
{
    [Test]
    public void can_construct_an_instance_of_the_SUT()
    {
        var connection = MockRepository.GenerateMock<IDbConnection>();
        var creditMaster = MockRepository.GenerateMock<ICreditMaster>();

        var creditValidator = new CreditValidator(connection, creditMaster);
        creditValidator.ShouldNotBeNull();
    }
}

 

This test should not throw an exception, I assert on null just to write a clear test. Run it, and surely enough the test passes.

------ Test started: Assembly: Koning.WEWLC.Tests.dll ------

1 passed, 0 failed, 0 skipped, took 1.35 seconds.

 

 

The Case of the Hidden Dependency

Once you get the class instantiated, we try to use it and bang! Some obscure other complex class is instantiated deep inside and causes the crash. Enter the "case of the hidden dependency". You need to remove newing the class and either move it to a public property or to the constructor. You can then either mock the constructor parameter or set it when you need through the property.

Once you start moving dependencies to the constructor of your classes it quickly starts to make sense to use a Dependency Injection Container. The one I use most frequently is Unity as it's included in EntLib and has several advantages over the other DI-containers available. For one that it's usage it's fairly simple, but even more so that is has Microsoft's backing, often a requirement at the projects I work.

 

Let's have a look at how such a configuration would look like for a hypothetical complex class Repository. First create an interface for the Repository and register it in the BootStrapper. Registration in the Unity container:

public static class BootStrapper
{
    
    public static IUnityContainer GetContainer()
    {
        var container = new UnityContainer();
        container.RegisterType<IRepository, Repository>();
        return container;
    }
}

public class Repository:IRepository
{
}

public interface IRepository
{
}

I prefer to use a static container to resolve dependencies in my applications, like so

public static class StaticContainer
{
    public static T Resolve<T>()
    {
        return BootStrapper.GetContainer().Resolve<T>();    
    }
}

Once the dependency is registered it is simply a matter of retrieving the SUT by requesting the container to construct it. In your tests you can then choose to have the container construct the dependencies or have Rhino Mocks generate the mocks after which you can set expectations on them.

 

The Case of the Construction Blob

If a constructor constructs a large number of objects internally or accesses a large number of globals, we could end up with a very large parameter list. One simple rule is to avoid the construction altogether and move the result of the creation logic into a dependency property. You could then have your DI container inject it at will or inject a mock when used in a test harness.

 

 

The case of the Irritating Global Dependency

In WEWLC, Michael Feathers writes: "Many different kinds of dependency can make it hard to create and use classes in a testing framework, but one of the hardest to deal with is global variable usage."

He's describing the hideous Singleton use in legacy code. Personally I haven't run into problems with a Singleton. Partly, because I didn't write tests at the time I was using them and on the other hand because nowadays I simply ask my DI container for a Singleton when I need it.

Still, Singletons can be a pain in the ass and you should try to avoid them. The whole idea of the singleton pattern is to make it impossible to create more than one instance of a singleton in an application. Because it is, it is particularly hard to fake. What do you do when you encounter one?

Basically you have three options, one is to replace all occurrences in the code; this can be a very tedious job, but with the aid of Resharper, one that I would recommend.

The other is to add a static method to the Singleton that will allow you to pass in a fake. First the lazy Singleton implementation (I have omitted any useful methods for  brevity):

public class PermitRepository
{
    protected PermitRepository() { }

    public static PermitRepository GetInstance()
    {
        return Nested.Instance;
    }

    public static void SetInstance(PermitRepository repository)
    {
        Nested.Instance = repository;
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        public static PermitRepository Instance
        {
            get { return instance; }
            set { instance = value; }
        }

        static PermitRepository instance = new PermitRepository();
    }
}

 

 

And to prove that getting multiple calls of the GetInstance() method will return the same object whilst using the SetInstance method will change the instance field the following test:

public class FakePermitRepository : PermitRepository
{
}
[TestFixture]
public class PermitRepositoryTests
{
    [Test]
    public void can_replace_the_PermitRepositoryInstance()
    {
        var repository = PermitRepository.GetInstance();
        int hashCode = repository.GetHashCode();

        hashCode.ShouldEqual(PermitRepository.GetInstance().GetHashCode());

        PermitRepository.SetInstance(new FakePermitRepository());
        PermitRepository.GetInstance().GetHashCode().ShouldNotEqual(hashCode);
    }
}

------ Test started: Assembly: Koning.WEWLC.Tests.dll ------

1 passed, 0 failed, 0 skipped, took 1.35 seconds.

 

The third option is to reset the private instance field of the Singleton and set it to null. First we alter the nested class a bit so that it checks for IsNull() before returning the object:

public class PermitRepository
{
    protected PermitRepository() { }

    public static PermitRepository GetInstance()
    {
        return Nested.Instance;
    }

    public static void SetInstance(PermitRepository repository)
    {
        Nested.Instance = repository;
    }

    public static void Reset()
    {
        Nested.Instance = null;
    }

    public

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        public static PermitRepository Instance
        {
            get
            {
                if (instance.IsNull())
                {
                    instance = new PermitRepository();
                }
                return instance;
            }
            set { instance = value; }
        }

        static PermitRepository instance = new PermitRepository();
    }
}

With the test to prove that the newly created Reset() method works as expected:

[Test]
public void can_reset_the_PermitRepositoryInstance()
{
    var repository = PermitRepository.GetInstance();
    int hashCode = repository.GetHashCode();

    hashCode.ShouldEqual(PermitRepository.GetInstance().GetHashCode());

    PermitRepository.Reset();
    PermitRepository.GetInstance().GetHashCode().ShouldNotEqual(hashCode);
}

------ Test started: Assembly: Koning.WEWLC.Tests.dll ------

2 passed, 0 failed, 0 skipped, took 0.93 seconds.

 

The Case of the Onion Parameter

In in many cases, it can be hard to create objects. Especially if they take other object that take other objects in their constructor. Every object needs to be set up in a good state, a state that makes it ready for additional work. This quite closely resembles a fat onion.

Every time when I introduce a DI container to the team I start working with I get the fat onion argument against using a DI container. Due to the steep object graph it becomes impossible to instantiate a class manually without having to instantiate many many others.

I always reply with, why bother. The DI container will take care of it. If you do find it cumbersome, apply Extract interface and inject a mock or a stub and you'll be done with it.

Feathers makes a huge point for simplicity in his WEWLC but with today's ease of use with DI containers I don't consider the argument to be valid anymore.

 

The case the aliased Parameter

If only pieces of a class that is used as a parameter causes problems, we can take another approach. If we subclass the dependency we don't have to create (yet) another interface. I personally have no issues whatsoever with many interfaces in a system as I'm a heavy Resharper user which navigating between classes and interfaces trivial.

When we've subclassed the dependency we can write any behavior we'd like to have in our fake. Obviously my preference would be to fake the class using Rhino Mocks for easy of setup and speed of writing.

 

Right, that concludes my second post on WEWLC, I can't get this class in a test harness. Hope you enjoyed it, let me know what you think.