Unity IoC container: tips, tricks and dirty hacks

by Marcin Kaluza 14. April 2012 08:20

It took me two years to write this post. Each time I started writing it, it suffered from gradual and seemingly unavoidable feature creep: should I mention dependency inversion principle? What about SOLID principles in general? What about testability? The list goes on and on. But it was a recent interesting discussion with a friend about the use (and abuse) of dependency injection that prompted me to finally finish it.

I have been using Unity IoC container for a while now and in the process I have managed to ”abuse” it in every possible way so I hope this post covers some of the more advanced and intricate usage scenarios you may ever come across.

Trivial case

In case you have never used Unity before, the behaviour of the container is pretty trivial: call Register<T,TImpl>() on a number of types then make a call to Resolve<T> and with a bit of luck you will get a instance of it:

    [TestFixture]
    class TrivialTests
    {
        [Test]
        public void TrivialOne()
        {
            var container = new UnityContainer();

            container.RegisterType<IBar, Bar>();

            var instance = container.Resolve<IBar>();

            Assert.NotNull(instance);
        }
    }

    internal class Bar : IBar {}
    internal interface IBar {}

Implementing a factory with Unity

Unity is not only able to resolve an implementation of a particular interface; it may also help in resolving dependencies when the type to be instantiated is known (even if it has not been registered with the container):

    [TestFixture]
    public class ObjectBuildupTest
    {
        [Test]
        public void ObjectBuildup()
        {
            var container = new UnityContainer();
            container.RegisterType<ISomeService, SomeService>();

            var anInstance = container.Resolve<ObjectWithDependencies>();

            Assert.NotNull(anInstance);
        }
    }

    public class ObjectWithDependencies
    {
        public ObjectWithDependencies(ISomeService  someService)
        {
            if (someService == null) throw new ArgumentNullException("someService");
        }
    }

    public interface ISomeService {}
    public class SomeService : ISomeService {}

As you can see from the code above, even though the type “ObjectWithDependencies” has not been registered with the container, Unity was able to correctly instantiate it and inject it with previously registered dependency. Such functionality may come very useful when implementing a factory: we know what we want to instantiate but not necessarily want to be bothered with instantiating all the dependencies. The following sample illustrates this approach.

    [TestFixture]
    public class FactoryTest
    {
        [Test]
        public void UnityBasedFactoryTest()
        {
            var container = new UnityContainer();

            container.RegisterType<ISomeService, SomeService>();
            container.RegisterType<ISomeFactory, SomeFactory>();

            var factory = container.Resolve<ISomeFactory>();

            Assert.NotNull(factory.ManufactureAnObject("A"));
        }
    }

    public interface ISomeFactory
    {
        ICommonInterface ManufactureAnObject(string anArgument);
    }

    public class SomeFactory : ISomeFactory
    {
        private readonly IUnityContainer _container;

        public SomeFactory(IUnityContainer container)
        {
            _container = container;
        }

        public ICommonInterface ManufactureAnObject(string anArgument)
        {
            switch(anArgument)
            {
                case "A":
                    return _container.Resolve<TypeA>();
                case "B":
                    return _container.Resolve<TypeB>();
                default:
                    throw new NotSupportedException();
            }
        }
    }

    public interface ICommonInterface {}

    public class TypeB : ICommonInterface
    {
        public TypeB(ISomeService someService)
        {            
        }
    }

    public class TypeA : ICommonInterface
    {
        public TypeA(ISomeService someService)
        {            
        }
    }

As you have probably noticed our factory requires an instance of IUnityContainer, luckily the container auto-registers itself, so whenever and instance of IUnityContainer is required, one will be injected without any fuss. Purists may frown upon direct use of the container, but in my opinion this is one of the very rare cases where it can be justified.

Multiple implementations of the same contract

The following example illustrates how to register multiple implementations of the same interface. Each registration is done with a particular key (quite a common feature among IoC containers) and then when resolving it we need to specify the key to get a particular implementation:

    [TestFixture]
    public class MultipleImplementationsTests
    {
        [Test]
        public void MultipleImplementations_ResolveCorrectly()
        {
            var container = new UnityContainer();
            container.RegisterType<IFooBar, SomeFooBar>("first");
            container.RegisterType<IFooBar, OtherFooBar>("second");

            Assert.NotNull(container.Resolve<IFooBar>("first"));
            Assert.NotNull(container.Resolve<IFooBar>("second"));
            Assert.Throws<ResolutionFailedException>(() => container.Resolve<IFooBar>());
        }
    }

    public interface IFooBar {}
    public class OtherFooBar : IFooBar {}
    public class SomeFooBar : IFooBar {}

This functionality can again be used to implement a factory of sorts but in general it is not that interesting until we get to the next point.

Building a composite

Having a multiple implementations of a particular contract registered with the container is the stepping stone to building a composite, as the following sample illustrates:

    [TestFixture]
    public class CompositeTests
    {
        [Test]
        public void BuildComposite()
        {
            var container = new UnityContainer();
            container.RegisterType<IFoo, SomeFoo>("first");
            container.RegisterType<IFoo, AnotherFoo>("second");
            container.RegisterType<IFoo, CompositeFoo>();

            var instanceOfFoo = container.Resolve<IFoo>();

            Assert.IsInstanceOf<CompositeFoo>(instanceOfFoo);
        }
    }

    public class CompositeFoo : IFoo
    {
        public CompositeFoo(IFoo[] others)
        {
            Debug.Assert(others != null);
            Debug.Assert(others.Any());
        }
    }

    public class AnotherFoo : IFoo {}
    public class SomeFoo : IFoo {}
    public interface IFoo {}

Composite in this case “consumes” an array of child objects and in a sense “sucks in” every implementation of IFoo registered with a key. This is an important aspect: if you were to register composite with a key, it would try to instantiate itself leading in immediately to StackOverflowException. The other interesting aspect is the fact that the composite requires an argument of type IChild[]. I am not sure about you but I personally find arrays very much 20th century and would rather have IEnumerable<IChild> injected, sadly Unity does not support it out of the box. There is however a workaround for it which I will share with you later.

Building chain of responsibility

Another interesting use case for naming your registrations is the implementation of Chain Of Responsibility pattern as the following sample illustrates:

    [TestFixture]
    class ChainOfResponsibilityTests
    {
        [Test]
        public void BuildChain()
        {
            var container = new UnityContainer();
            container.RegisterType<IChainLink, LastLink>("last");
            container.RegisterType<IChainLink, SecondLink>("second",
                                                           new InjectionConstructor(
                                                               new ResolvedParameter<IChainLink>("last")));
            container.RegisterType<IChainLink, FirstLink>(new InjectionConstructor(
                                                               new ResolvedParameter<IChainLink>("second")));

            var firstLink = container.Resolve<IChainLink>();

            Assert.IsInstanceOf<FirstLink>(firstLink);
        }
    }

    internal interface IChainLink {}

    internal class FirstLink : IChainLink
    {
        public FirstLink(IChainLink nextLink)
        {
            if (nextLink == null) throw new ArgumentNullException("nextLink");
        }
    }

    internal class SecondLink : IChainLink
    {
        public SecondLink(IChainLink nextLink)
        {
            if (nextLink == null) throw new ArgumentNullException("nextLink");
        }
    }

    internal class LastLink : IChainLink {}

 

In this case we need to resort to pointing each registered element of the chain to its predecessor which is achieved using ResolvedParameter<T>(name). This way we have full control as to what registration gets injected where. This may come helpful in cases where different implementations of the same contract are to be injected in different places.

Injecting the same object in multiple places in the object graph (semi-singleton)

Unity has a very interesting feature which allows the same object to be injected and shared in multiple places in the object graph. Let’s consider the following object diagram

:image

As you can see both the parent and the children contain references to an instance of Service. Standard behaviour of the IoC container is to inject new instance of the dependency into every object in the graph, this however may not be what we want:

image

In order to solve this conundrum Unity provides PerResolveLifetimeManager which within a single call to Resolve<T>() will create an instance of particular type and reuse it wherever required as the next sample illustrates:

    [TestFixture]
    public class PerResolutionLifetimeTests
    {
        [Test]
        public void Regiser_WithPerResolveLifetimeManager_ContainerInjectsSameInstance()
        {
            var container = new UnityContainer();
            container.RegisterType<IService, AService>(new PerResolveLifetimeManager());
            container.RegisterType<IParent, Parent>();
            container.RegisterType<IChild, Child>();

            var parent = container.Resolve<IParent>();

            Assert.AreSame(parent.Service, parent.Child.Service);
        }
    }

    public interface IService {}
    public class AService : IService {}
    public interface IChild
    {
        IService Service { get; set; }
    }

    public class Child : IChild
    {
        public IService Service { get; set; }

        public Child(IService service)
        {
            Service = service;
        }
    }

    public interface IParent
    {
        IChild Child { get; set; }
        IService Service { get; set; }
    }

    public class Parent : IParent
    {
        public IChild Child { get; set; }
        public IService Service { get; set; }

        public Parent(IChild child, IService service)
        {
            Child = child;
            Service = service;
        }
    }

Eternal problem: Chicken and Egg

Now there is an interesting chicken and egg problem which may seem to be impossible to solve using IoC container:

    
    public interface IEgg
    {
        IChicken Chicken { get; set; }
    }

    public interface IChicken
    {
        IEgg Egg { get; set; }
    }

    public class Chicken : IChicken
    {
        public IEgg Egg { get; set; }
    }

    public class Egg : IEgg
    {
        public Egg(IChicken chicken)
        {
            Chicken = chicken;
        }

        public IChicken Chicken
        {
            get;
            set;
        }
    }

As you can see we have a circular dependency going on here (Chicken “contains” an egg, while the egg points to its parent). This may seem to be a hopeless case but there is a solution to it: we need to combine property injection with PerResolveLifetimeManager:

[Test]
public void BuildObjectGraphWithCircularDependency()
{
    var container = new UnityContainer();

    container.RegisterType<IChicken, Chicken>(new PerResolveLifetimeManager(), new InjectionProperty("Egg"));
    container.RegisterType<IEgg, Egg>();

    var chicken = container.Resolve<IChicken>();

    Assert.AreSame(chicken, chicken.Egg.Chicken);
}

The magic above works as follows: container instantiates an instance of the Chicken class and then tries to resolve the Egg dependency. Egg in turn requires another instance of Chicken, luckily the Chicken class has been registered with PerResolveLifetimeManager which means it that instance of it can be reused in building the Egg. I think the case above is the only one I can think of where the use of property injection could be justified.

IoC and Interface segregation principle

There are some cases where a single type implements multiple contracts (interfaces). If you follow interface segregation principle this may lead to some troublesome cases:

[Test]
public void Resolve_ObjectDependantOnBaseInterface_ResolutionFails()
{
    var container = new UnityContainer();
    
    container.RegisterType<IDerived, Derived>();
    container.RegisterType<IDependsOnBase, DependsOnBase>();

    Assert.Throws<ResolutionFailedException>(() => container.Resolve<IDependsOnBase>());
}

public interface IBase { }
internal interface IDerived : IBase { }
internal class Derived : IDerived { }

public interface IDependsOnBase { }

public class DependsOnBase : IDependsOnBase
{
     public DependsOnBase(IBase dependency){}
}

As you can see from the code above, Derived implements IDerived which in turn is an instance of IBase. Inspite of that, resolution of DependsOnBase fails miserably. The reason is obviously the fact that there is no explicit implementation of IBase registered with the container. We could circumvent the problem by registering the Derived as type implementing the IBase interface. This approach would work but what if Derived implements more than one interface? There is however an easy way to work around the issue and this requires a hint to the container that instead of IBase it should search for an implementation of IDerived:

[Test]
public void Resolve_ObjectDependantOnBaseInterface_ResolutionSucceeds()
{
    var container = new UnityContainer();

    container.RegisterType<IDerived, Derived>();
    container.RegisterType<IDependsOnBase, DependsOnBase>(new InjectionConstructor(typeof(IDerived)));

    Assert.DoesNotThrow(() => container.Resolve<IDependsOnBase>());
}

This way btw it is the way to construct a composite using IEnumerable<> instead of an array as mentioned previously.

Overriding constructor parameters

The final set of Unity tricks deals with overriding constructor parameters. As you may remember we did this to a certain extent when registering individual elements of the chain of responsibility. There are two ways to do it: we can either instruct container at the time of registration to use specific instance of the parameters, or override parameter value at the time of resolution. Following sample illustrates both techniques.

[TestFixture]
public class ConstructorParameters
{
    [Test]
    public void OverridingCtorParams()
    {
        var container = new UnityContainer();
        container.RegisterType<SomeType>(new InjectionConstructor("Boo"));
        
        var firstInstance = container.Resolve<SomeType>();
        Assert.AreEqual("Boo", firstInstance.Message);

        var secondInstance = container.Resolve<SomeType>( new ParameterOverride("message", "Baa"));
        Assert.AreEqual("Baa", secondInstance.Message);
    }
}

public class SomeType
{
    public string Message { get; set; }

    public SomeType(string message)
    {
        Message = message;
    }
}
Tags:
Categories: C# | Software Development

How to focus on the wrong thing when writing code

by John Rayner 19. July 2011 04:42

A recent discussion on our mailing list revolved around the use of regions, and whether stripping them out of a codebase was a useful first task when joining a new project!  The conclusion was, sensibly, that there were more likely bigger fish to fry (especially since region outlining can easily be disabled in your IDE) and so regions should be left alone.  Along the way, however, someone voiced an opinion that the software devs have a professional responsibility to adhere to existing standards.

Consistency in code is a great aid to readability – no doubt about it – but often someone needs to be the first to write a unit test, for example.  The benefit that comes about from automated testing massively outweighs any benefit from uniform code, by many orders of magnitude.  Similar arguments apply to use of IOC, good design of code, proper consideration of class / method / variable names, refactoring, SOLID principles and so on.  All of these things are simply more important than whether you group all your methods into a region named “Methods” or not.  And unfortunately, none of these items can be adequately codified into standards – it’s simply not possible.

Curiously, coding standards are so mechanical that they can actually be captured by software and fixes can be automatically applied.  These are the only coding standards that I personally ever bother to try and apply on a project.  I want development tools to be worrying about capitalisation, the presence or absence of underscores at the start of variable names, positioning of braces, and so on.  I do not want developers to concern themselves with such issues – the time and brain power of a good developer is simply too valuable to waste on such niceties.

Adherence to coding standards is just like tidying the decks of a ship.  It’s a good thing to do … just make sure that you aren’t on a Titanic that is slowly sinking into the deep!

Bob the builder

by Michael Ciba 5. November 2010 22:43

I recently started a new project which is very focused on having good test coverage which is great goal to have.  However, looking through their tests I started to notice a lot of setup code which was very similar and looked a lot like the following:

   1: [TestMethod]
   2: public void WhenTheAddressRepositoryIsAskedToAPersistAddressesItShouldCorrectlyPersistThoseAddresses()
   3: {
   4:     // Arrange
   5:     var addressesToPersist = new List<Address>();
   6:  
   7:     var address = new Address
   8:                           {
   9:                               AddressLine1 = Guid.NewGuid().ToString(),
  10:                               AddressLine2 = Guid.NewGuid().ToString(),
  11:                               AddressLine3 = Guid.NewGuid().ToString(),
  12:                               AddressLine4 = Guid.NewGuid().ToString(),
  13:                               City = Guid.NewGuid().ToString(),
  14:                               County = Guid.NewGuid().ToString(),
  15:                               CountryCode = Guid.NewGuid().ToString(),
  16:                               Postcode = Guid.NewGuid().ToString()
  17:                           };
  18:     addressesToPersist.Add(address);
  19:  
  20:     var address1 = new Address
  21:                            {
  22:                                AddressLine1 = Guid.NewGuid().ToString(),
  23:                                AddressLine2 = Guid.NewGuid().ToString(),
  24:                                AddressLine3 = Guid.NewGuid().ToString(),
  25:                                AddressLine4 = Guid.NewGuid().ToString(),
  26:                                City = Guid.NewGuid().ToString(),
  27:                                County = Guid.NewGuid().ToString(),
  28:                                CountryCode = Guid.NewGuid().ToString(),
  29:                                Postcode = Guid.NewGuid().ToString()
  30:                            };
  31:     addressesToPersist.Add(address1);
  32:  
  33:     var addressRepository = new AddressRepository();
  34:     
  35:     // Act
  36:     addressRepository.Persist(addressesToPersist);
  37:     var actualPersistedAddresses = addressRepository.GetAll();
  38:     
  39:     // Assert
  40:     Assert.IsNotNull(actualPersistedAddresses);
  41:     Assert.AreEqual(2, actualPersistedAddresses.Count);
  42: }

Now the above code isn’t all that bad in a single test but what happens when you start to write more tests?  Well you could copy and paste the code for creating addresses from test to test which will certainly work but you end up with a lot of very similar code which you have to maintain going forward and update whenever a new address property is added or removed.  All this sounds like a lot of work plus it goes against the DRY principle.  DRY for those of you who don’t know means “Don’t Repeat Yourself”.  The principle encourages that duplication within an application is removed as every line of  code written has to be maintained and each line of code can cause bugs. More importantly the principle is about having a single source of knowledge within a system and then using that source to generate instances of that knowledge. In this case the instances of knowledge would be the address objects which are being created within each unit test.  The question then is how do we create something which we can use as the source of that knowledge?

Enter the builder

That single source of knowledge within the project I’m working on is provided by using the object builder pattern. Using this pattern we can have a single and consistent approach to creating the entities within tests and the ability to easily extend those entities within our domain and test data. We can also chain the builders together to create complex test data very quickly.

So how do you create a builder? Well below is my implementation of an address builder to get you going.

   1: public class AddressBuilder : BuilderBase<AddressBuilder, Address>
   2: {
   3:     private int id;
   4:     private string addressLine1 = GetUniqueValueFor();
   5:     private string addressLine2 = GetUniqueValueFor();
   6:     private string addressLine3 = GetUniqueValueFor();
   7:     private string addressLine4 = GetUniqueValueFor();
   8:     private string city = GetUniqueValueFor();
   9:     private string countryCode = "GB";
  10:     private string postCode = "SE1 9EU";
  11:     private string county = "London";
  12:  
  13:     public AddressBuilder WithId(int id)
  14:     {
  15:         this.id = id;
  16:         return this;
  17:     }
  18:    
  19:     public AddressBuilder WithAddressLine1(string addressLine1)
  20:     {
  21:         this.addressLine1 = addressLine1;
  22:         return this;
  23:     }
  24:  
  25:     public AddressBuilder WithAddressLine2(string addressLine2)
  26:     {
  27:         this.addressLine2 = addressLine2;
  28:         return this;
  29:     }
  30:  
  31:     public AddressBuilder WithAddressLine3(string addressLine3)
  32:     {
  33:         this.addressLine3 = addressLine3;
  34:         return this;
  35:     }
  36:  
  37:     public AddressBuilder WithAddressLine4(string addressLine4)
  38:     {
  39:         this.addressLine4 = addressLine4;
  40:         return this;
  41:     }
  42:  
  43:     public AddressBuilder WithCity(string city)
  44:     {
  45:         this.city = city;
  46:         return this;
  47:     }
  48:  
  49:     public AddressBuilder WithCountry(string countryCode)
  50:     {
  51:         this.countryCode = countryCode;
  52:         return this;
  53:     }
  54:  
  55:     public AddressBuilder WithPostCode(string postCode)
  56:     {
  57:         this.postCode = postCode;
  58:         return this;
  59:     }
  60:  
  61:     public AddressBuilder WithCounty(string county)
  62:     {
  63:         this.county = county;
  64:         return this;
  65:     }
  66:  
  67:     public override Address Build()
  68:     {
  69:         var address = new Address
  70:                           {
  71:                               Id = this.id,
  72:                               AddressLine1 = this.addressLine1,
  73:                               AddressLine2 = this.addressLine2,
  74:                               AddressLine3 = this.addressLine3,
  75:                               AddressLine4 = this.addressLine4,
  76:                               City = this.city,
  77:                               CountryCode = this.countryCode,
  78:                               County = this.county,
  79:                               Postcode = this.postCode
  80:                           };
  81:  
  82:         return address;
  83:     }
  84: }

As you can see the code behind the builder is really very simple with default values assigned to the properties which can then be explicitly set using the “With” methods on the builder. When I’m using builders I also like to add a base for them which provides default behaviour.

   1: public abstract class BuilderBase<TBuilder, TBuild> where TBuilder : BuilderBase<TBuilder, TBuild>
   2: {
   3:     /// <summary>
   4:     /// Builds this instance.
   5:     /// </summary>
   6:     /// <returns></returns>
   7:     public abstract TBuild Build();
   8:  
   9:     /// <summary>
  10:     /// Builds the many.
  11:     /// </summary>
  12:     /// <param name="number">The number.</param>
  13:     /// <returns></returns>
  14:     public List<TBuild> BuildMany(int number)
  15:     {
  16:         var result = new List<TBuild>();
  17:  
  18:         for (int i = 0; i < number; i++)
  19:         {
  20:             var builtItem = this.Build();
  21:             result.Add(builtItem);
  22:         }
  23:  
  24:         return result;
  25:     }
  26:  
  27:     /// <summary>
  28:     /// Gets the unique value for.
  29:     /// </summary>
  30:     /// <returns></returns>
  31:     protected static string GetUniqueValueFor()
  32:     {
  33:         return Guid.NewGuid().ToString();
  34:     }
  35: }

So now we have the address builder this put it all together to create our new and improved unit test.

   1: [TestMethod]
   2: public void WhenTheAddressRepositoryIsAskedToAPersistAddressesItShouldCorrectlyPersistThoseAddresses()
   3: {
   4:     // Arrange
   5:     var addressesToPersist = new AddressBuilder().BuildMany(2);
   6:     var addressRepository = new AddressRepository();
   7:     
   8:     // Act
   9:     addressRepository.Persist(addressesToPersist);
  10:     var actualPersistedAddresses = addressRepository.GetAll();
  11:     
  12:     // Assert
  13:     Assert.IsNotNull(actualPersistedAddresses);
  14:     Assert.AreEqual(2, actualPersistedAddresses.Count);
  15: }

As you can see the duplicate code for creating each address is now gone and we have a nice simple method for creating as many address as we want using the “BuildMany” method provided by the base builder. Well that’s it for now. The complete source code for this example can be found at http://cid-468e9f9e14e99f80.office.live.com/self.aspx/.Public/Blog.Builders.zip

Rules of Unit Testing

by Marcin Kaluza 24. June 2010 08:26

There is hopefully no need for me to discuss the benefits of unit testing but with more and more shops adopting agile, “scrum-but” or other TDD-like processes, people start to realise that it’s not all plain sailing. One of the major headaches related to unit testing is the cost of maintaining the tests themselves. Unless you get smart about your testing approach, growing number of unit tests may become a drag over time seriously increasing the cost of any change, becoming a hindrance rather than help.

In order to be successful with any form of TDD it’s worthwhile to consider some basic rules. With notable exceptions of posts by Szczepan Faber and Michael Feathers, Google renders rather poor results on the subject so I decided to give it another go. What you are (hopefully) about to read is the result of the learning I have received with other #Fellows in the “school of hard knocks”. We have learned by our, sometimes grave, mistakes so be smart and do not repeat them.

Rob C. Martin in his Clean Code mentions the following FIRST rules when it comes to unit testing. According to the rules unit tests should be:

  • Fast, as otherwise no-one will want to run them,
  • Independent as otherwise they will affect each other’s results
  • Repeatable in any environment
  • Self-validating (either failing or passing)
  • written in a Timely manner (together with the code being tested, not in some yet undetermined “future”)

The rules are by all means valuable but when it comes to practice of programming we need to get a bit more detailed. So let’s start with the basics

Design for testing

The prerequisite to successful unit tests is the “testability” of the code, and for the code to be testable you need to be able to inject it with mock implementation of dependencies. In practice it means that database, network, file, UI etc access has to be hidden behind some form of abstraction (interface). This gives us the possibility to use mocking framework to construct those dependencies and cheaply test various combinations of test inputs. The other obvious benefit is the fact that your tests become independent of difficult to maintain external “variables” as there is no need to deploy files, databases etc. When it comes to UI dependencies (using UI controls etc)  avoid them in your testable code as they may introduce thread affinity which cannot always be guaranteed by the environment/test runner.

The testable architecture naturally gravitates towards SOLID design principles as individual classes tend to have single responsibility and have every chance to remain “solid” regardless of the project timescales and turns in direction it may take.

Do not repeat yourself

The primary sin of unit testing is repetition and it is easy to explain it: you start with one test of your class Foo. Then you  add another test scenario, so now both of them will have to get an instance of Foo from somewhere and they will obviously “new()” the Foo. Then you will have more methods to tests and more lines of new Foo(). And one day you will need to add a parameter to Foo’s constructor and suddenly all those pesky tests will need to be reworked. You may argue that it should be easy enough to add an overload, but sometimes fabrication of objects gets more complicated: you need to use properties, call some methods on them etc. For this reason my advice is: Do not Repeat Yourself (stay DRY), use factory methods, builders etc in order to avoid the costs of refactoring which will inevitably get you one day. Funnily enough John Rayner of this shire produced recently a very nice automocking container which helps in instantiating types with large number of dependencies.

I find it quite interesting that developers are often willing to accept substantially lower coding standards when it comes to unit tests, often copy-pasting entire test cases only to change one line within it. Before you realise it, your test code base becomes a tangled, repeatable mess and introducing any change becomes a serious cost and challenge. If you ever come across a situation when you need to test similar cases over and over again, re-factor a common method, use a template method pattern or row based testing as implemented in NUnit etc but please, do not repeat yourself!

Keep the intent clear

How many times have you come across a test methods called “Test1”? Not a very helpful name, isn’t it? The purpose of the tests should be crystal clear as otherwise it may be very difficult to decipher over time the original intent. And if the intent needs to be ever deciphered, it adds to the cost of change. I have worked once on a project where the cost of refactoring tests was substantially higher than the cost of changing the code itself and other than violation of the DRY rule, the primary reason was the difficulty of “rebuilding” the tests so that they tested the original behaviour exactly as intended. To make the intent of the test clear I try to follow these rules:

  • Have a consistent naming convention for tests and test methods: say Ctor_WIthInvalidArgs_ThrowsException(). This naming convention outlines what is being tested, how it is being tested and what is expected. Or better yet…
  • Consider using NBehave to specify your expectations and assumptions. Side effect of using NBehave is the fact that your expectations and assumptions become crystal clear
  • Follow “triple A” structure for test methods (Arrange, Act Assert) and make it obvious in the test code what are you doing
  • Test one thing (method, property, behaviour) per test method
  • Add messages to asserts. Asserting that (a == b)  won’t tell you much when the expectation gets violated.

Do not share static state

In order to stick with the Isolation rule, it’s good practice to give up on shared static state as it is very easy to introduce frustrating dependencies between tests. Other than this, static variables are either difficult or impossible to mock, or lead to seriously hacked code (a singleton with a setter etc). For this reasons any statics, singletons etc have to be avoided for the sake of testability. If you think of this restriction as harsh, think again: there is always a way to replace your singleton with another pattern (say a factory returning a shared instance) which at the end of the day produces the same results, yet is far easier to test and more flexible in the long term.

Avoid mega-tests

I sometimes come across a phenomenon which I call mega-test: this usually involves running a process end-to-end and producing some output file (usually in 10s of MBs) which is then compared to a “master” file with the expectation that it has to be identical. This is probably the worst ever way to test software and the only circumstances where it could be acceptable practice is when refactoring a system which has no unit tests whatsoever. The problem with tests like this is the fact that when they fail, investigating the cause of failure is very expensive as you will have to trawl through tons of code to get to the bottom of the problem. Test failure should make you smarter and you should be able to say what went wrong pretty much immediately. Do not get me wrong, I am not saying here that you should not have “integration tests”. But the fact remains that majority of the testing work should be done through unit testing of individual components rather than slow and laborious “end to end” testing which often requires difficult preparation, setup and deployment.

Avoid strict mocks

This is another constant source of grief as strict mocks do not allow your code to deviate from pre determined expectations: so strict mock will accept the calls you set it to, but anything other than this will fail. If the code under test changes a little and does a bit less or more with the mock, the test will fail and you will need to revisit it adding extra expectations. Do not get me wrong here, strict mocks are valuable tool, but be very careful how you use them and ask yourself what exactly are you testing?

Maintain symmetry

Symmetry between code being tested and unit tests is all about 1:1 relationship between the code and it’s unit tests: so you have one test fixture per class, one test project per assembly etc. The reason for this symmetry is the fact that if you do change a class, there is (hopefully) only one test fixture which you need to execute to get a good idea if the code still works. This setup makes life easier as if you run your tests constantly you do not have to run all of them all the time. It also becomes easier to package code together with tests in cases you want to share it with someone.

Szczepan Faber mentions that testing class hierarchies is difficult and I agree with him, but my approach to resolving this problem is slightly different. If you maintain symmetry, every type (including base and derived types) will have a corresponding test fixture, which means that you will not get into a situation where you test the base through tests designed for the derived class. This is a rather uncomfortable as you will potentially have the same functionality tested multiple times, or worse yet, when the derived type gets scraped, your base class will be left “uncovered”. Maintaining the symmetry will help you alleviate this issue.

Maintaining the symmetry may be tricky in case of abstract types which cannot be instantiated, but in this case you can either derive a special “test only” type or use one of the already derived types hidden behind a factory of sorts.

Get clever

Sometimes in large projects it becomes necessary to follow certain convention in your unit tests, e.g. it sometimes makes sense to run the tests within transaction scope, or follow certain Setup/Teardown standards. In such cases you may want to derive all test fixtures from a common base, and to enforce the rule, write a test inspecting all test fixtures through reflection making sure that the test classes do indeed use common base class. I used this approach in the past to isolate all integration tests from each other through transaction scope.

Do not get too clever!

The most frustrating test failures are related to someone being unusually clever and writing a test which for example sets value held in a private field using reflection as the code cannot be tested otherwise. Then you happen to rename this field in good faith and everything builds, you do not see any reason to run the tests, check in your code and the integration build bombs out. Not a pretty sight but it’s an evil practice so please do not try to get overly smart with your testing.

Tags: