【问题标题】:Chaining Customizations with Autofixture使用 Autofixture 链接自定义
【发布时间】:2015-02-26 11:33:39
【问题描述】:

我知道Autofixture 在找到满足请求的ISpecimenBuilder 时会停止构建对象。因此,当我应用几个后续自定义时,除了最后一个之外的所有自定义都会被忽略。我该如何组合自定义?也就是说,我该如何修改这个sn-p:

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

要等价于这个sn-p:

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

【问题讨论】:

  • 简短的回答是您不能这样做使用 AutoFixture 开箱即用,这是设计使然。多年前的某个时候,我实际上有一个原型,它的行为就像你想要的那样,而不是覆盖以前的定制,但在尝试了一段时间后,我得出的结论是它也是当事情变得更加复杂时,可能会导致一些难以理解的行为。在我使用 AutoFixture 的很多年里,我也从来没有需要这样做,所以我对用例很好奇。
  • @MarkSeemann 用例是应用类似流利的界面。因此,我可以使用fixture.WithEmail().WithCache(),而不是fixture.SetupWithEmailAndCache()。启用电子邮件和启用缓存都需要在配置对象上设置某些属性以及其他一些操作。但是这些属性或操作不会与电子邮件和缓存相交,因此将此类设置放入单个函数是没有意义的。
  • 感谢您的澄清。如果您通常需要在相同的测试代码中解决独立的问题,那么这对您的被测系统有何影响?
  • @MarkSeemann 我看不出有什么问题 - 你怎么能测试一个依赖于其他相互独立的单元的单元?我的示例有什么问题是,即使我声称我的电子邮件和缓存独立,它们确实有一些共同点 - 这就是配置对象。这违反了单一职责原则并导致测试出现问题。另一个例子——我有一个对整个测试套件通用的定制;仅在一个测试用例中,我想稍微更改设置,但为此我需要复制整个自定义设置。

标签: c# autofixture


【解决方案1】:

这是我想出的:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    相关资源
    最近更新 更多