使用FromSeed自定义AutoFixure导致异常
本文关键字:异常 AutoFixure FromSeed 自定义 使用 | 更新日期: 2023-09-27 18:21:19
给定两个类:
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
对象,而不会有任何问题。但是,一旦我尝试创建一个具有Foo
属性的Bar
对象,我就会得到一个ObjectCreationException
:
修饰的ISpecimenBuilder无法基于请求创建样本:Foo。如果请求表示一个接口或抽象类,就会发生这种情况;如果是这种情况,请注册一个ISpecimenBuilder,它可以根据请求创建样本。如果这种情况发生在强类型Build表达式中,请尝试使用IFactoryComposer方法之一提供工厂。
我希望TestFooFactory
在创建Bar
的过程中传递一个null
种子值,就像我创建没有种子值的Foo
一样。我是做错了什么,还是这可能是一个bug?
在我的真实场景中,当我传入种子值时,我想自定义AutoFixture如何为某些对象使用种子值,但如果没有提供种子,我仍然希望AutoFixture默认为正常行为。
自定义Fixture
以使用种子值的方式是正确的。
您看到的行为是FromSeed
自定义如何修改AutoFixture管道的结果。如果你有兴趣了解细节,我在这里已经描述过了。
作为一种变通方法,您可以为种子请求使用自定义样本生成器,如以下所示:
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)));
当填充类型为Foo
的属性时,此自定义将把default(Foo)
(即null
)作为种子传递给TestFooFactory
工厂函数。