![](/img/trans.png)
[英]AutoFixture: Freeze runtime type throws no public constructor error
[英]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.