AutoFixture 是否可以创建具有所有相同数据的给定类型的多个实例?我的类不可序列化,我需要两个不是引用等效的模型,而是具有匹配的属性。
public class Foo
{
// Many more properties and similar models needing the same semantics.
public string Name { get; set; }
}
var a = fixture.Create<Foo>();
var b = fixture.Create<Foo>();
Assert.False(ReferenceEquals(a, b));
Assert.Equal(a.Name, b.Name);
答案 0 :(得分:0)
我不认为AutoFixture可以做到这一点,但Albedo可以。虽然这只是概念验证代码,但我希望它应该说明一般的想法。
创建一个新类,派生自public class PropertyCopyVisitor<T> : ReflectionVisitor<T>
{
private readonly T source;
private readonly T destination;
public PropertyCopyVisitor(T source, T destination)
{
this.source = source;
this.destination = destination;
}
public override IReflectionVisitor<T> Visit(
PropertyInfoElement propertyInfoElement)
{
var pi = propertyInfoElement.PropertyInfo;
pi.SetValue(this.destination, pi.GetValue(this.source));
return this;
}
public override T Value
{
get { return this.destination; }
}
}
:
Visit
实施的关键部分是source
重载,它使用Reflection将每个属性从destination
复制到destination
对象。
由于此实现会改变Value
,因此永远不会使用abstract
属性,但它必须存在,因为它ReflectionVisitor<T>
中的var fixture = new Fixture();
var a = fixture.Create<Foo>();
var b = fixture.Create<Foo>(); // Or just create a new, empty Foo...
// This copies all properties from a to b:
new TypeElement(typeof(Foo)).Accept(new PropertyCopyVisitor<Foo>(a, b));
Assert.False(ReferenceEquals(a, b));
Assert.Equal(a.Name, b.Name);
...
您现在可以将测试编写为:
fixture
在这里,我仍然使用b
来创建Foo
,但您不必这样做,因为无论如何都会覆盖所有属性。如果new Foo()
具有无参数构造函数,则可以简单地使用Visit
;它没有任何区别。
此概念验证明确仅复制属性。如果您还需要复制字段,那么您也必须覆盖相应的new TypeElement(typeof(Foo)).Accept(new PropertyCopyVisitor<Foo>(a, b));
方法。此外,如果有问题的对象采用构造函数参数,那么您也需要明确地处理这些对象。
如果你发现写PropertyCopyVisitor
很乏味,我相信你可以找到一种方法来编写辅助方法。
作为补充说明,T
是通用的,因为它实际上并没有使用{{1}}类型参数。我只是喜欢它给构造函数的类型安全性......