Today I tried to fix an automatic build on TFS. The build was failing because of the unit tests. The reason was simple but hard to figure. Let’s imagine the following scenario.
We have an interface IPet and we implement it in two dll’s, HousePets in a class Cat and in GardenPets in class Badger.

namespace HousePets
{
    public class Cat : IPets.IPet
    { ... }
}

namespace GardenPets
{
    public class Dog : IPets.IPet
    { ... }
}

namespace IPets
{
    public interface IPet
    { ... }
}

And extra we have another class which is a loads an assembly and returns an implementation of IPet from one of the 2 dll’s.

public IPets.IPet GetCat()
{
    Assembly catAssembly = Assembly.Load("HousePets.dll");
    return (IPets.IPet)Activator.CreateInstance(catAssembly.GetType("Cat"));
}

Naturally this class is in a project that has no refference to either HousePets nor GardenPets.
If we have a unit test that uses it, in order for it to run, we just add the two projects as references to ensure that HousePets.dll and GardenPets.dll will be present in the bin directory of the unit test project.

While this works on the local machine, when ran in a TFS build environment it will crash. The reason is the static analysis that the TFS is starting. This is not detecting any object of type Cat or Badger and thus the libraries HousePets.dll and GardenPets.dll are not copied in the run directory.

The sollution is simple. Add a class in your unit project:

public class AssemblyInjector
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance"
        "CA1804:RemoveUnusedLocals", MessageId = "c")]
    public AssemblyInjector()
    {
        // make a call to a class of the library we want to be also copied in the
        // test directory
        HousePets.Cat c = new HousePets.Cat();
    }
}

{ Disclaimer: don’t mind the implementation, it’s only there for illustrating the problem and the sollution }

Leave a Reply