XUnit& AutoFixture:使用不同的数据组合运行测试(多个AutoDataAttributes)

时间:2015-09-14 09:17:53

标签: c# unit-testing xunit autofixture

可能是个愚蠢的问题,第一次我真的在写一个单元测试(对我来说很遗憾)。我正在使用Xunit和AutoFixture。 所以,我有一些单元测试,我想用不同的输入数据组合运行。

例如,假设我正在测试我的DAL并希望使用不同类型的存储库(例如内存和SQL)测试相同的单元测试。我还需要创建一些其他数据,这些数据将由单元测试和存储库使用。 我的一些类需要通过工厂方法创建,因为它们没有任何公共构造函数。

我的理想是做

之类的事情
[Theory, InMemoryRepository, SomeOtherData]
[Theory, SqlRepository, SomeOtherData]
// ... some other data combinations ...
public void SomeTest(IRepository repository, ISomeOtherData someOtherData)
{
    // do some tests here
}

public class InMemoryRepositoryAttribute : AutoDataAttribute
    {

    public InMemoryRepositoryAttribute()
    {
        Fixture.Register<IRepository>(CreateRepository);
    }

    protected IRepository CreateRepository()
    {
        var data = Fixture.CreateMany<ISomeOtherData>().ToList();  // this will throw an exception "AutoFixture was unable to create an instance (...)" as my binding doesn't seem be available in the Fixture
        var repository = new InMemoryDAL.Repository();
        repository.Insert(data);

        return repository;
    }
}

public class SomeOtherDataAttribute : AutoDataAttribute
{
    public SomeOtherDataAttribut()
    {
        Fixture.Register<ISomeOtherData>(CreateData);
    }

    protected ISomeOtherData CreateData()
    {
        string test = Fixture.Create<string>();
        var data = (new SomeOtherDataFactory()).Create(test);
        return data;
    }
}

但这不起作用,因为我的AutoDataAttribute类似乎都是基于单独的灯具。即我在SomeOtherDataAttribute中注册的内容似乎在我的InMemoryRepositoryAttribute实例中不可用。

有没有办法解决这个问题?使用属性在Fixture中组合不同的数据集?

或者您会建议哪些替代方案 - 最好为每个数据组合创建单独的测试函数,并从那里明确调用SomeTest()?

谢谢!

1 个答案:

答案 0 :(得分:4)

实际上,您可以通过定义允许自定义类型的供应数组的自定义AutoDataAttribute来实现此目的。以下是如何完成此任务的示例:

public class CompositeCustomizationsAttribute : AutoDataAttribute
{
    public CompositeCustomizationsAttribute(params Type[] customizationTypes)
    {
        foreach (var type in customizationTypes)
        {
            var customization = (ICustomization)Activator.CreateInstance(type);
            Fixture.Customize(customization);
        }
    }
}

public class InMemoryRepositoryCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Register<IRepository>(() => CreateRepository(fixture));
    }

    protected IRepository CreateRepository()
    {
        var data = Fixture.CreateMany<ISomeOtherData>().ToList();
        var repository = new InMemoryDAL.Repository();
        repository.Insert(data);

        return repository;
    }
}

public class SomeOtherDataCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Register<ISomeOtherData>(() => CreateData(fixture));
    }

    protected ISomeOtherData CreateData()
    {
        string test = Fixture.Create<string>();
        var data = (new SomeOtherDataFactory()).Create(test);
        return data;
    }
}

鉴于上述自定义项和CompositeCustomizationsAttribute,您现在可以定义测试方法:

[Theory, CompositeCustomizations(typeof(InMemoryRepositoryCustomization), typeof(SomeOtherDataCustomization))]
public void SomeTest(IRepository repository, ISomeOtherData someOtherData)
{
    // do some tests here
}