如何在保留类型自定义的同时使用AutoFixture构建自定义属性? [英] How to use AutoFixture to build with customized properties while keeping type customizations?

查看:78
本文介绍了如何在保留类型自定义的同时使用AutoFixture构建自定义属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use autofixture to create an object but there are certain properties that I want to always be defaulted (while the rest could be auto generated). However, whenever I setup an customization it gets overwritten when I build with customizations.

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;}
}

Name DateOfBirth 属性自定义设置没有冲突,因此我不知道为什么Name最终为空.我希望名称是 Ben .

The Name and DateOfBirth property customizations do not conflict so I don't know why Name ends up being null. I would expect name to be Ben.

如何获取它以便应用两种自定义设置(即 Name ="Ben" DateOfBirth = 1/1/1900 )?

How can I get it so both customizations are applied (ie. Name = "Ben" and DateOfBirth = 1/1/1900)?

推荐答案

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

As @DavidOsborne correctly pointed out, the behavior you are seeing is as designed.

更好的方法是将您的自定义内容组织在单独的类中,然后根据特定测试场景的需要启用它们.

A better approach is to organize your customizations in separate classes and then enable them as needed by a specific test scenario.

定制对象实现 ICustomization 接口,其任务是以特定方式配置 Fixture 对象.这是一个示例:

A customization object implements the ICustomization interface and its job is to configure the Fixture object in a specific way. Here's an example:

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 上启用自定义,例如:

You can enable a customization on a specific Fixture by using the Customize method, for example:

fixture.Customize(new AllPersonsAreNamedBen());

或:

fixture.Customize(new AllPersonsAreBornIn1900());

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

You can also combine multiple customizations into a new one by using the CompositeCustomization class:

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

这时您可以简单地说:

fixture.Customize(new AllPersonsAreNamedBenAndAreBornIn1900());

但是,请记住,对 Fixture 进行自定义的顺序很重要:最后一个获胜,并且可能覆盖,例如@MarkSeemann在评论中指出.这也是通过设计.

However, keep in mind that the order in which the customizations are applied on a Fixture matters: the last one wins and can potentially override the previous ones, as @MarkSeemann pointed out in the comments. This, too, is by design.

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

So, while you can combine existing customizations that work on different types, in this particular case, since both customizations target the same type, you'll have to create a new customization to encapsulate all the settings for the Person type combined:

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)));
    }
}

通常,保持较小的自定义内容和重点可以使您

As a general rule, keeping your customizations small and focused enables you to reuse them in different tests, combining them for specific test scenarios.

这篇关于如何在保留类型自定义的同时使用AutoFixture构建自定义属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆