繁体   English   中英

使用自动混合创建结构不会引发公共构造函数错误

[英]Creating a struct with autofixture throws no public constructor error

我有一个结构,例如:

public struct Foo
{
    public int Bar;
    public string Baz;
}

并希望使用自动混合在我的单元测试中创建它。 我尝试使用以下内容:

IFixture fixture = new Fixture();
var f = fixture.CreateAnonymous<Foo>();

但这会引发AutoFixture was unable to create an instance错误。 是否可以使用自动混合自动创建结构? 怎么可以这样做? 请注意,我正在处理遗留代码,因此需要处理结构。 :)

编辑:

IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());

IFixture fixture = new Fixture();

因为它与这个问题无关。

这实际上是C#编译器如何处理值类型的人工制品。 虽然文档似乎另有说明 ,但从反射的角度来看,Foo结构没有公共构造函数。

例如,如果您执行此代码:

var ctors = typeof(Foo).GetConstructors();

结果是一个空数组。

但是,此代码编译:

var f = new Foo();

所以你可以说AutoFixture应该能够创建一个Foo实例。

然而,最终, 可变结构是邪恶的 ,应该不惜一切代价避免。 更好的选择是将Foo实现更改为:

public struct Foo
{
    public Foo(int bar, string baz)
    {
        this.Bar = bar;
        this.Baz = baz;
    }

    public readonly int Bar;
    public readonly string Baz;
}

如果这样做,您现在不仅具有(更多)正确的值类型,而且AutoFixture还能够创建实例而无需进一步修改。

因此,这是GOOS范例的一个很好的例子,您应该听取您的测试 如果它们存在摩擦,则可能是有关生产代码的反馈。 在这种情况下,这正是你要用脚射击自己的反馈,因为价值类型的实现是有缺陷的。

PS即使你“修复”上面概述的Foo结构,有什么意义使它成为结构而不是类? 它仍然包含一个字符串(引用类型)字段,因此即使结构本身将存在于堆栈中,字符串字段仍将指向堆中的数据。


我已将此问题添加为AutoFixture的可能新功能。

从这篇博客文章中得到ISpecimenBuilder ,我创建了一个实现ISpecimenBuilder的类

class FooBuilder : ISpecimenBuilder
{
  public object Create(object request, ISpecimenContext context)
  {
    var sr = request as SeededRequest;
    if (sr == null)
    {
        return new NoSpecimen(request);
    }
    if (sr.Request != typeof(Foo))
    {
        return new NoSpecimen(request);
    }

    var foo = new Foo();
    foo.Bar = context.CreateAnonymous<int>();
    foo.Baz = context.CreateAnonymous<string>();
    return foo;
  }
}

并将该类添加为自定义

fixture.Customizations.Add(new FooBuilder());

导致对CreateAnonymous<Foo>的调用工作。

如果有一个更开箱即用的解决方案,请发布它,我会接受它作为答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM