鉴于这两个类:
RecyclerView
我已经设置了以下测试:
class Foo
{
...
}
class Bar
{
public Foo FooBar { get; set; }
}
我可以使用和不使用种子值直接创建void Test()
{
var fixture = new Fixture();
fixture.Customize<Foo>(x => x.FromSeed(TestFooFactory));
var fooWithoutSeed = fixture.Create<Foo>();
var fooWithSeed = fixture.Create<Foo>(new Foo());
var bar = fixture.Create<Bar>(); //error occurs here
}
Foo TestFooFactory(Foo seed)
{
//do something with seed...
return new Foo();
}
个对象而没有任何问题。但是,一旦我尝试创建具有Foo
属性的Bar
对象,我就会得到Foo
:
装饰的ISpecimenBuilder无法根据请求创建样本:Foo。如果请求表示接口或抽象类,则会发生这种情况;如果是这种情况,请注册一个可以根据请求创建标本的ISpecimenBuilder。如果在强类型的Build表达式中发生这种情况,请尝试使用其中一个IFactoryComposer方法提供工厂。
我希望ObjectCreationException
在创建TestFooFactory
期间传递null
种子值,就像我创建没有种子值的Bar
一样。我做错了什么,或者这可能是个错误?
在我的真实场景中,我想自定义当我传入种子值时,AutoFixture如何使用某些对象的种子值,但如果没有提供种子,我仍然希望AutoFixture默认为正常行为。
答案 0 :(得分:5)
您自定义Fixture
以使用种子值is correct的方式。
您看到的行为是FromSeed
自定义修改AutoFixture管道的结果。如果您有兴趣阅读详细信息,我已将其描述为here。
作为一种解决方法,您可以使用自定义样本构建器来处理这样的种子请求:
public class RelaxedSeededFactory<T> : ISpecimenBuilder
{
private readonly Func<T, T> create;
public RelaxedSeededFactory(Func<T, T> factory)
{
this.create = factory;
}
public object Create(object request, ISpecimenContext context)
{
if (request != null && request.Equals(typeof(T)))
{
return this.create(default(T));
}
var seededRequest = request as SeededRequest;
if (seededRequest == null)
{
return new NoSpecimen(request);
}
if (!seededRequest.Request.Equals(typeof(T)))
{
return new NoSpecimen(request);
}
if ((seededRequest.Seed != null)
&& !(seededRequest.Seed is T))
{
return new NoSpecimen(request);
}
var seed = (T)seededRequest.Seed;
return this.create(seed);
}
}
然后,您可以使用它来创建类型为Foo
的对象:
fixture.Customize<Foo>(c => c.FromFactory(
new RelaxedSeededFactory<Foo>(TestFooFactory)));
此自定义将在填充default(Foo)
类型的属性时将null
- 即TestFooFactory
- 作为Foo
工厂函数的种子传递。