使用 Autofixture 链接自定义

Chaining Customizations with Autofixture

我知道 Autofixture 在找到可以满足请求的 ISpecimenBuilder 时停止构建对象。因此,当我应用多个后续自定义时,除了最后一个之外的所有自定义都会被忽略。我该如何合并自定义项?换句话说,我该如何修改这个片段:

fixture.Customize<SomeClass>(ob => ob.With(x => x.Id, 123)); // this customization is ignored
fixture.Customize<SomeClass>(ob => ob.With(x => x.Rev, 4341)); // only this one takes place

与此代码段等效:

fixture.Customize<SomeClass>(ob => ob
    .With(x => x.Id, 123)
    .With(x => x.Rev, 4341)); // both customization are applied

这是我想出的:

public class CustomFixture : Fixture
{
    public CustomFixture ()
    {
        this.Inject(this);
    }

    private readonly List<object> _transformations = new List<object>();

    public void DelayedCustomize<T>(Func<ICustomizationComposer<T>, ISpecimenBuilder> composerTransformation)
    {
        this._transformations.Add(composerTransformation);
    }

    public void ApplyCustomize<T>()
    {
        this.Customize<T>(ob =>
        {
            return this._transformations.OfType<Func<ICustomizationComposer<T>, ISpecimenBuilder>>()
                .Aggregate(ob, (current, transformation) => (ICustomizationComposer<T>)transformation(current));
        });
    }

}

以及用法:

var fixture = new CustomFixture();

fixture.DelayedCustomize<SomeClass>(ob => ob.With(x => x.Id, 123)); 
fixture.DelayedCustomize<SomeClass>(ob => ob.With(x => x.Rev, 4341)); 
fixture.ApplyCustomize<SomeClass>();

var obj = fixture.Create<SomeClass>();
// obj.Id == 123
// obj.Rev == 4341

不理想,因为需要 ApplyCustomize