【问题标题】:How to use AutoFixture to build with customized properties while keeping type customizations?如何使用 AutoFixture 在保持类型自定义的同时使用自定义属性进行构建?
【发布时间】:2016-07-31 22:34:45
【问题描述】:

我正在尝试使用 autofixture 创建一个对象,但我希望始终默认某些属性(而其余属性可以自动生成)。但是,每当我设置自定义项时,当我使用自定义项进行构建时,它都会被覆盖。

void Main()
{
    var fixture = new Fixture();
    fixture.Customize<Person>(composer => composer.With(p => p.Name, "Ben"));

    var person = fixture.Build<Person>()
        .With(p => p.DateOfBirth, new DateTime(1900, 1, 1))
        .Create();

    /*  RESULT OF person below
    Name    null
    DateOfBirth 1/1/1900
    StreetAddress   StreetAddressafd6b86b-376a-4355-9a9c-fbae34731453
    State   State019e867b-ac5e-418f-805b-a64146bc06bc
    */
}

public class Person
{
    public string Name { get; set;}

    public DateTime DateOfBirth { get; set;}

    public string StreetAddress { get; set;}

    public string State { get; set;}
}

NameDateOfBirth 属性自定义不冲突,所以我不知道为什么 Name 最终为空。我希望名字是Ben

我怎样才能得到它以便同时应用两个自定义项(即Name = "Ben"DateOfBirth = 1/1/1900)?

【问题讨论】:

    标签: c# .net unit-testing autofixture


    【解决方案1】:

    正如@DavidOsborne 正确指出的那样,您看到的行为是as designed

    better approach 是在单独的类中组织您的自定义,然后根据特定测试场景的需要启用它们。

    自定义对象实现ICustomization 接口,其工作是以特定方式配置Fixture 对象。这是一个例子:

    public class AllPersonsAreNamedBen : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<Person>(composer =>
                composer.With(p => p.Name, "Ben"));
        }
    }
    
    public class AllPersonsAreBornIn1900 : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<Person>(composer =>
                composer.With(p => p.DateOfBirth, new DateTime(1900, 1, 1)));
        }
    }
    

    您可以使用Customize 方法对特定Fixture 启用自定义,例如:

    fixture.Customize(new AllPersonsAreNamedBen());
    

    或:

    fixture.Customize(new AllPersonsAreBornIn1900());
    

    您还可以使用 CompositeCustomization 类将多个自定义组合成一个新的:

    public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization
    {
        public AllPersonsAreNamedBenAndAreBornIn1900()
            : base(new AllPersonsAreNamedBen(),
                   new AllPersonsAreBornIn1900())
        {
        }
    }
    

    此时你可以简单地说:

    fixture.Customize(new AllPersonsAreNamedBenAndAreBornIn1900());
    

    但是,请记住,在 Fixture 上应用自定义的顺序很重要:正如@MarkSeemann 在厘米。这也是by design

    因此,虽然您可以组合适用于不同类型的现有自定义,但在这种特殊情况下,由于两个自定义针对同一类型,因此您必须创建一个新的自定义来封装 Person 类型的所有设置组合:

    public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<Person>(composer =>
                composer.With(p => p.Name, "Ben")
                        .With(p => p.DateOfBirth, new DateTime(1900, 1, 1)));
        }
    }
    

    作为一般规则,保持您的自定义小且集中使您能够在不同的测试中reuse them,将它们组合用于特定的测试场景。

    【讨论】:

    • AllPersonsAreNamedBen不是要去overrideAllPersonsAreBornIn1900吗?
    • 我的立场是正确的。由于两种自定义都适用于同一类型,因此它们绝对可以。谢谢你叫出来!这是 AutoFixture 不时困扰我的一个方面——我希望我可以像这样糟糕逐步组合多个自定义项,以至于我有时会忘记这是不可能的。
    • 投反对票,因为它具有误导性 - 您不能组合自定义一种类型的两个自定义项。更新这个答案会很好,因为它的支持率最高。
    • @wirher 我明确地写道:“因此,虽然您可以组合适用于不同类型的现有自定义项,但在这种特殊情况下,由于两个自定义项都针对相同的类型,因此您必须创建一个新的自定义来封装 Person 类型组合的所有设置"。它是如何误导的?
    【解决方案2】:

    这看起来像是设计使然:

    请注意,最好将 Build 方法链理解为一次性自定义。它绕过Fixture 实例上的所有自定义。相反,它允许在构建特定样本时进行细粒度控制。但是,在大多数情况下,添加基于约定的ICustomization 是更好、更灵活的选择。

    ...来自Build() 方法的文档。

    我明白这可能不是一个理想的答案。但是,该文档确实提供了有关您如何实现的提示。

    【讨论】:

      【解决方案3】:

      正如接受的答案所指出的,自定义将相互覆盖,因此您必须为要使用的每个属性组合编写自定义。

      我编写了一个库,允许您编写自定义项,这样它们就不会相互覆盖,而是合并在一起。这将允许您为People named Ben 和一个Born in 1900 自定义一个,并且您可以将它们与 Compose 函数组合在一起。

      它并没有完全解决最初的问题,但它可能会给你一些关于如何实现你想要的想法。 Compose 函数是通过创建一个处理自定义的自定义 IFixture 实现来完成的。

      https://github.com/LethargicDeveloper/Lift.AutoFixture

      编辑:我看到“4 个月前活跃”。我错过了“3年”。很抱歉复活了这么旧的帖子,但希望这会有用。

      【讨论】:

      • 你删除了repo吗?链接坏了:(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-01
      相关资源
      最近更新 更多