我在这个实例中使用AutoFixture来具体化包含Mongo ObjectId的对象,像这样
Fixture fixture = new Fixture();
fixture.Register(ObjectId.GenerateNewId);
但是我每次考试都这样做。是否有可能以某种方式为所有测试注册这个全局?
没有办法全局(或静态)做到这一点。
我通常做的是创建一个TestConventions
类,其中包含我想应用于每个测试的所有自定义。
internal class TestConventions : CompositeCustomization
{
public TestConventions() :
base(
new MongoObjectIdCustomization())
{
}
private class MongoObjectIdCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(ObjectId.GenerateNewId);
}
}
}
然后我将这些约定应用到每个测试中:
var fixture = new Fixture().Customize(new TestConventions());
如果你正在使用AutoFixture。XUnit2(或AutoFixture.NUnit)插件,你可以通过定义一个导入测试约定的属性来减少这个样板文件:
public class MyProjectAutoDataAttribute : AutoDataAttribute
{
public MyProjectAutoDataAttribute() : base(
new Fixture().Customize(new TestConventions()))
{
}
}
然后将它应用到您的测试用例中:
[Theory, MyProjectAutoData]
public void SomeFact(SomeClass sut)
{
}
我按照@drcastro的建议创建了一个约定类,但我最终创建了一个TestBase类,我继承了我的单元测试类
public class TestBase
{
public IFixture GenerateNewFixture()
{
return new Fixture().Customize(new AutoFixtureConventions());
}
}
internal class AutoFixtureConventions : CompositeCustomization
{
public AutoFixtureConventions() :
base(
new MongoObjectIdCustomization())
{
}
private class MongoObjectIdCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(ObjectId.GenerateNewId);
}
}
}
你也可以这样做
public class FixtureWithFoo: Fixture
{
public FixtureWithFoo()
{
Customizations.Add(new FooCustomization());
//Or register something else
}
}
然后在你的测试
中使用它var fixture = new FixtureWithFoo();
我通过注册ISpecimenBuilder来解决这个问题,因为我需要匹配有关PropertyInfo的一些标准。
private class MongoObjectIdSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request is PropertyInfo info
&& info.PropertyType == typeof(ObjectId)
&& ...)
return ObjectId.GenerateNewId().ToString();
return new NoSpecimen();
}
}
// register the builder
AutoFixture.Customizations.Add(new MongoObjectIdSpecimenBuilder());