XUnit & AutoFixture:运行 具有不同数据组合的测试(多个 AutoDataAttributes)
XUnit & AutoFixture: Running a test with different data combinations (several AutoDataAttributes)
可能是个愚蠢的问题,我第一次真正编写单元测试(我感到羞耻)。我正在使用 Xunit 和 AutoFixture。
因此,我有一些单元测试,我想 运行 使用不同的输入数据组合。
例如,假设我正在测试我的 DAL 并想用不同类型的存储库(例如内存和 SQL)测试相同的单元测试。我还需要创建一些其他数据,单元测试和存储库都将使用这些数据。
我的一些 类 需要通过工厂方法创建,因为它们没有任何 public 构造函数。
我的理想是做类似
的事情
[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-类 似乎都基于单独的装置。 IE。我在 SomeOtherDataAttribute 中注册的任何内容在我的 InMemoryRepositoryAttribute 实例中似乎都不可用。
有什么方法可以解决这个问题并使用属性在 Fixture 中组合不同的数据集吗?
或者您会建议什么替代方案 - 也许最好为每个数据组合创建单独的测试函数,然后从那里显式调用 SomeTest()?
谢谢!
实际上,您可以通过定义允许提供自定义类型数组的自定义 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
}
可能是个愚蠢的问题,我第一次真正编写单元测试(我感到羞耻)。我正在使用 Xunit 和 AutoFixture。 因此,我有一些单元测试,我想 运行 使用不同的输入数据组合。
例如,假设我正在测试我的 DAL 并想用不同类型的存储库(例如内存和 SQL)测试相同的单元测试。我还需要创建一些其他数据,单元测试和存储库都将使用这些数据。 我的一些 类 需要通过工厂方法创建,因为它们没有任何 public 构造函数。
我的理想是做类似
的事情[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-类 似乎都基于单独的装置。 IE。我在 SomeOtherDataAttribute 中注册的任何内容在我的 InMemoryRepositoryAttribute 实例中似乎都不可用。
有什么方法可以解决这个问题并使用属性在 Fixture 中组合不同的数据集吗?
或者您会建议什么替代方案 - 也许最好为每个数据组合创建单独的测试函数,然后从那里显式调用 SomeTest()?
谢谢!
实际上,您可以通过定义允许提供自定义类型数组的自定义 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
}