Search code examples
c#nunittestcasesource

NUnit: How to run a test class on multiple objects - better alternative than TestCaseSourceAttribute?


I want to test all implementations of an interface with the same test class. I already know the TestCaseSourceAttribute, so I have set it up to load the object instances from the static testObjects array. This code works as I want:

[TestFixture]
public class MySerializerTests
{
    // IStreamSerializers loaded by the TestCaseSource attribute.
    static object[] testObjects = new object[]
    {
        new BinarySerializer(),
        new XmlSerializer(),
        new JsonSerializer()
    };

    [Test, TestCaseSource("testObjects")]
    public void Serialize_NullStreamArgument_ThrowsArgumentException(IStreamSerializer serializer)
    {
        Map map = new Map();
        Assert.Throws<ArgumentNullException>(() => serializer.Serialize(null, map));
    }
}

However, I have to use [TestCaseSource("testObjects")] on every method, which makes it rather tedious for the amount of methods I have. Is there a way of replacing the TextCaseSource attribute with an attribute that works on the whole test class? Maybe similar to the way a parameterized FestFixture works?

I'd like something similar to this, but where I can pass instances of my tested classes via the constructor of the test class:

[TestFixture(0)]
[TestFixture(1)]
[TestFixture(2)]
public class MySerializerTests
{
    // IStreamSerializers loaded by the TestCaseSource attribute.
    static object[] testObjects = new object[]
    {
        new BinarySerializer(),
        new XmlSerializer(),
        new JsonSerializer()
    };

    int currentIndex;

    public MySerializerTests(int index)
    {
        currentIndex = 0;
    }

    [Test]
    public void Serialize_NullStreamArgument_ThrowsArgumentException()
    {
        Map map = new Map();

        Assert.Throws<ArgumentNullException>(() => testObjects[currentIndex].Serialize(null, map));
    }
}

Solution

  • You want the TestFixtureSourceAttribute.

    [TestFixtureSource("testObjects")]
    public class MySerializerTests
    {
        // IStreamSerializers loaded by the TestCaseSource attribute.
        static IStreamSerializer[] testObjects = new IStreamSerializer[]
        {
            new BinarySerializer(),
            new XmlSerializer(),
            new JsonSerializer()
        };
    
        IStreamSerializer _serializer;
    
        public MySerializerTests(IStreamSerializer serializer)
        {
            _serializer = serializer;
        }
    
        [Test]
        public void Serialize_NullStreamArgument_ThrowsArgumentException()
        {
            Map map = new Map();
            Assert.Throws<ArgumentNullException>(
                () => _serializer.Serialize(null, map));
        }
    }
    

    I haven't compiled this, so you may need to fix typos, etc.