编程语言
首页 > 编程语言> > c# – 使用FromSeed自定义AutoFixure会导致异常

c# – 使用FromSeed自定义AutoFixure会导致异常

作者:互联网

鉴于这两个类:

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:

The decorated ISpecimenBuilder could not create a specimen based on the request: Foo. This can happen if the request represents an interface or abstract class; if this is the case, register an ISpecimenBuilder that can create specimens based on the request. If this happens in a strongly typed Build expression, try supplying a factory using one of the IFactoryComposer methods.

我希望TestFooFactory在创建Bar期间传递一个null种子值,就像我创建没有种子值的Foo一样.我做错了什么,或者这可能是一个错误?

在我的实际场景中,我想自定义当我传入种子值时,AutoFixture如何使用某些对象的种子值,但是如果没有提供种子,我仍然希望AutoFixture默认为正常行为.

解决方法:

您自定义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)));

当填充Foo类型的属性时,此自定义将传递默认值(Foo) – 即null – 作为TestFooFactory工厂函数的种子.

标签:c,unit-testing,autofixture
来源: https://codeday.me/bug/20190519/1136340.html