【问题标题】:AutoFixture Without() method does not work when there is only 1 constructor with all parameters?当只有 1 个具有所有参数的构造函数时,AutoFixture Without() 方法不起作用?
【发布时间】:2022-12-14 02:19:14
【问题描述】:

我有以下课程:

public class Foo
{
  public Foo(string id, 
     string name, 
     string? homeTown = null, 
     IEnumerable<string>? someCollection = null)
  {
     Id = id;
     Name = name;  
     HomeTown = homeTown;
     SomeCollection = someCollection;
  }

  public string Id { get; set; }
  public string Name {get; set;}
  public string? HomeTown {get; set;}
  public IEnumerable<string>? SomeCollection {get; set;}
}

我想在不填充 HomeTown 和 SomeCollection 的情况下使用 AutoFixture 创建模拟。

但是当我尝试像这样创建它时,属性仍然会被填充!

    Fixture fixture = new Fixture();

    var dto = fixture.Build<Foo>()
        .Without(x => x.HomeTown)
        .Without(x => x.SomeCollection)
        .Create();

如果我添加另一个没有 hometown 和 somecollection 的构造函数 - 它会起作用,但我不想添加另一个构造函数只是为了满足测试。

为什么会出现这种行为?这是 AutoFixture 中的某种错误吗?

有办法解决吗?

【问题讨论】:

    标签: c# autofixture


    【解决方案1】:

    据我所知,这是 AutoFixture 的预期行为,也是它推动开发人员进行更好设计的方式。

    AutoFixture 是 TDD 的(自以为是的)工具,围绕 80-20 规则构建,因此它确实对您将如何设计代码做出了一些假设,并且它实现了大多数常见情况下使用的大部分功能。

    也就是说,它也是一个非常开放的工具,具有很大的灵活性。这意味着您可以告诉它省略任何可选参数。

    您可以通过创建一个构建器来实现它,该构建器返回为可选参数设置的默认值,然后省略所有自动属性。

    class OptionalParameterSpecification : IRequestSpecification
    {
        public bool IsSatisfiedBy(object request)
            => request is ParameterInfo parameterInfo
            && parameterInfo.IsOptional;
    }
    
    class DefaultValueParameterBuilder : ISpecimenBuilder
    {
        private readonly IRequestSpecification specification;
    
        public DefaultValueParameterBuilder(IRequestSpecification specification)
        {
            this.specification = specification
                ?? throw new ArgumentNullException(nameof(specification));
        }
    
        public object Create(object request, ISpecimenContext context)
        {
            if (!this.specification.IsSatisfiedBy(request)) return new NoSpecimen();
            if (request is not ParameterInfo parameterInfo) return new NoSpecimen();
    
            return parameterInfo.DefaultValue;
        }
    }
    

    使用上面的构建器,您的测试应该如下所示。

    [Fact]
    public void Bar()
    {
        var fixture = new Fixture();
        fixture.Customizations.Add(
            new DefaultValueParameterBuilder(
                new OptionalParameterSpecification()));
        fixture.Customize<Foo>(c => c.OmitAutoProperties());
    
        var foo = fixture.Create<Foo>();
    
        Assert.NotNull(foo.Id);
        Assert.NotNull(foo.Name);
        Assert.Null(foo.HomeTown);
        Assert.Null(foo.SomeCollection);
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-23
      • 2022-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 2012-11-03
      • 1970-01-01
      相关资源
      最近更新 更多