如何使用带有 ICustomization、ISpecimenBuilder 的 Autofixture (v3) 来处理构造函数参数? [英] How do I use Autofixture (v3) with ICustomization, ISpecimenBuilder to deal with constructor parameter?

查看:12
本文介绍了如何使用带有 ICustomization、ISpecimenBuilder 的 Autofixture (v3) 来处理构造函数参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试克服一个场景,其中一个类具有一个字符串构造函数参数,该参数不能被 Autofixture 生成的任何旧字符串(Guid-y 外观值)所满足.

I'm trying to overcome a scenario in which a class has a string constructor parameter which cannot be satisfied by any old string generated by Autofixture (the Guid-y looking value).

在您想简单地通过一个链接来回答之前,Mark Seemann 的 Ploeh 博客关于公约的条目-基于自定义,让我说我一直在参考它和他的其他博客条目以进行此测试,但我无法通过.

Before you're tempted to answer simply with a link to Mark Seemann's Ploeh blog entry on Convention-based Customizations, let me say that I've been referencing it and other blog entries of his for this test, which I can't get to pass.

当我逐步调试时,我可以看到在某些时候构造函数参数以有效值传入,但测试仍然以 Guid-y Color 值失败.我认为这与以下事实有关,即有一个颜色"参数值,一个由 Autofixture 填充的颜色"属性.是不是我写了一个 ISpecimenBuilder 来处理构造函数参数,但我正在测试公共属性值(两个不同的东西)?

When I step through in debug, I can see that at some point the constructor parameter is passed in with the valid value, but the test still fails with the Guid-y Color value. I think this has something to do with the fact that there is both a 'color' parameter value, and a 'Color' property to be populated by Autofixture. Is it that I've written an ISpecimenBuilder that addresses the constructor parameter, but I'm testing the public property value (two different things)?

我知道所有这些对于示例来说都是多余的,但我设想了一个更复杂的场景,其中使用 Build().With() 方法不会是 DRY.

I know that all this is overkill for the example, but I envision a more complicated scenario in which using the Build<T>().With() method would not be DRY.

失败的测试

    [Fact]
    public void Leaf_Color_Is_Brown()
    {
        // arrange
        var fixture = new Fixture().Customize(new LeafColorCustomization());

        // act
        var leaf = fixture.Create<Leaf>();

        // using .Build<>.With(), test passes
        //var leaf = fixture.Build<Leaf>().With(l => l.Color, "brown").CreateAnonymous();

        // assert
        Assert.True(leaf.Color == "brown");
    }

SUT

    public class Leaf
    {
        public Leaf(string color)
        {
            if (color != "brown")
                throw new ArgumentException(@"NO LEAF FOR YOU!");

            this.Color = color;
        }
        public string Color { get; set; }
    }

CompositeCustomization 实现(我知道在这个例子中不需要 AutoMoqCustomization())

The CompositeCustomization implementation (I know the AutoMoqCustomization() isn't needed in this example)

    public class LeafCustomization : CompositeCustomization
    {
        public LeafCustomization()
            : base(
            new LeafColorCustomization(),
            new AutoMoqCustomization()) { }
    }

特定于叶子的 ICustomization

    public class LeafColorCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            if (fixture == null)
                throw new ArgumentNullException("fixture");

            fixture.Customizations.Add(new LeafBuilder());
        }
    }

带有颜色名称的字符串构造函数 ISpecimenBuilder

    public class LeafBuilder : ISpecimenBuilder
    {
        public object Create(object request, ISpecimenContext context)
        {
            var pi = request as ParameterInfo;
            if (pi == null)
                return new NoSpecimen(request);

            if (pi.ParameterType != typeof(string) || pi.Name != "color")
                return new NoSpecimen(request);

            return "brown";
        }
    }

推荐答案

解决方案 1:

注册 Color 可写属性不应作为后处理的一部分分配任何自动值:

Register that the Color writable property should not be assigned any automatic value as part of the post-processing:

internal class LeafColorCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customize<Leaf>(c => c
            .Without(x => x.Color));

        fixture.Customizations.Add(new LeafBuilder());
    }
}

解决方案 2:

Color 属性设为只读:

public class Leaf
{
    private readonly string color;

    public Leaf(string color)
    {
        if (color != "brown")
            throw new ArgumentException(@"NO LEAF FOR YOU!");

        this.color = color;
    }

    public string Color
    {
        get { return this.color; }
    }
}

由于 Color 属性是只读的,AutoFixture 不会为其分配值.

Since the Color property is read-only AutoFixture is not going to assign a value for it.

上述解决方案也适用于 AutoFixture 2.

The above solutions apply also to AutoFixture 2.

这篇关于如何使用带有 ICustomization、ISpecimenBuilder 的 Autofixture (v3) 来处理构造函数参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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