MbUnit TypeFixture and Providers

Continuing in my writing about MbUnit, this post will focus on the TypeFixtureAttribute. The TypeFixture allows a set of tests to focus on testing a certain type of class (generally an interface) and to provide objects of that type to be tested against.

This method is really useful if you have a collection of objects which all have similar behaviour which requires testing. Instead of having to duplicate your test code, you can define the types to be tested with instances of the tests being passed into the test being executed.

In my fake system being tested, I have a collection of objects which all implement a INotNull interface. I need to test to make sure that the implementation of INotNull works correctly, that not nulls are returned when GetNotNullValues() is called. My ‘Production’ code is this:

public interface INotNull
{
IEnumerable GetNotNullValues();
}

public class TypeA : INotNull
{
public override string ToString()
{
return “TypeA”;
}

public IEnumerable GetNotNullValues()
{
yield return “TypeA”;
}
}

public class TypeB : INotNull
{
public override string ToString()
{
return “TypeB”;
}

public IEnumerable GetNotNullValues()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}
}

public class TypeC : INotNull
{
public override string ToString()
{
return “TypeC”;
}

public IEnumerable GetNotNullValues()
{
yield return new object();
yield return null;
yield return new object();
}
}

The code looks fine, apart from TypeC which returns a null. In a standard unit testing framework, I would have to create multiple test fixtures for each type in the system and duplicate all of the tests. TypeFixture makes our life easier by allowing us to define a single fixture and test all the objects we want. Let’s have a look at the test code.

[TypeFixture(typeof(INotNull), “Tests the INotNull interface.”)] #1
public class INotNullTests

Instead of defining a TestFixture at the top of our class, we define a TypeFixture and give it the typeof object we will be testing. We then need to tell it all the objects to use.

[Provider(typeof(TypeA))] #1
public TypeA ProvideTypeA()
{
return new TypeA(); #2
}

#1 We use the ProviderAttribute and provide the type of object we are returning as a parameter.

#2 We then create a new instance of the object and return it to the caller.

We can use the Provider attribute on as many methods as required to cover all of our objects being tested. The other two objects being tested are TypeB and TypeC.

[Provider(typeof(TypeB))]
public TypeB ProvideTypeB()
{
return new TypeB();
}

[Provider(typeof(TypeC))]
public TypeC ProvideTypeC()
{
return new TypeC();
}

Now we have that in place, we need to write out tests. The test is a standard test, however accepts the type (as defined in the TypeFixture) as a parameter.

[Test]
public void TestINotNullValuesNotNull(INotNull instance)
{
Console.WriteLine(instance.ToString());

foreach (object o in instance.GetNotNullValues())
{
Assert.IsNotNull(o, “Instance: {0}. Object was null: {1}”, instance, o);
}
}

We can then use that object within our test to verify it works correctly. This test method will be called once per object defined by a provider attribute. In this case, three tests are executed with TypeC test failing.

image

Adding more tests to the fixture is very quick and easy and with the TypeFixture will result in it being used to test multiple objects. Adding another implementation of the interface is easy as we define another method allowing it to be picked up by all the existing tests.

Technorati Tags: , ,

One thought on “MbUnit TypeFixture and Providers”

  1. Hi,

    Having to type

    [Provider(typeof(TypeA))]
    public TypeA ProvideTypeA()
    {
    return new TypeA();
    }

    all the time looks like a lot of boilerplate code. Sure I can invent a snippet, but isn’t it possible to do such things automatically? Unless TypeA doesn’t have a default constructor, I mean.

    ulu

Leave a Reply

Your email address will not be published. Required fields are marked *