Nat*_*n A 5 c# unit-testing autofixture
鉴于这两个类:
class Foo
{
...
}
class Bar
{
public Foo FooBar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我已经设置了以下测试:
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();
}
Run Code Online (Sandbox Code Playgroud)
我可以Foo使用和不使用种子值直接创建对象而没有任何问题.但是一旦我尝试创建一个Bar具有Foo属性的对象,我得到一个ObjectCreationException:
装饰的ISpecimenBuilder无法根据请求创建样本:Foo.如果请求表示接口或抽象类,则会发生这种情况; 如果是这种情况,请注册一个可以根据请求创建标本的ISpecimenBuilder.如果在强类型的Build表达式中发生这种情况,请尝试使用其中一个IFactoryComposer方法提供工厂.
我期望在创建过程中TestFooFactory传递null种子值Bar,就像我在Foo没有种子值的情况下创建时一样.我做错了什么,或者这可能是一个错误?
在我的实际场景中,我想自定义当我传入种子值时,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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用它来创建Foo类似以下类型的对象:
fixture.Customize<Foo>(c => c.FromFactory(
new RelaxedSeededFactory<Foo>(TestFooFactory)));
Run Code Online (Sandbox Code Playgroud)
当填充类型的属性时default(Foo),此自定义将传递- 即null作为TestFooFactory工厂函数的种子Foo.
| 归档时间: |
|
| 查看次数: |
681 次 |
| 最近记录: |