gpt4 book ai didi

c# - 单个对象创建时的 AutoFixture 自定义

转载 作者:行者123 更新时间:2023-11-30 17:40:48 24 4
gpt4 key购买 nike

所以,我有一个具有很多 IEnumerable 属性的对象。在单元测试中我想做这样的事情:

var subsequentAgreement = _fixture.Build<Foo>()
.With(dto => dto.Bars,
_fixture.CreateMany<Bar>())
.Create();

还有另一个IEnumerable<T>我想要一个 Enumerable.Empty<T>() 的属性

我有一个 ISpecimenBuilder

public class EmptyEnumerableBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
object returnObject = new NoSpecimen(request);
var type = request as Type;
if (type != null && type.IsGenericType)
{
var typeArguments = type.GetGenericArguments();
if(!typeArguments.Any() || typeof(IEnumerable<>) == type.GetGenericTypeDefinition())
returnObject = Array.CreateInstance(typeArguments.Single(), 0);
}

return returnObject;
}
}

我这样添加:_fixture.Customizations.Add(new EmptyEnumerableBuilder());这工作得很好,除了我创建的所有其他对象现在都有 Empty 枚举。

我正在寻找应用此 EmptyEnumerableBuilder 的方法对于单个 _fixture.Build<>()并保留其余的默认值,但我似乎找不到办法。

我试过像这样使用类型限制:

_fixture.Customize<SubsequentAgreementLimitationsDto>(composer => new EmptyEnumerableBuilder());

但奇怪的是,fixture 创建的所有其他对象仍然有空的枚举

最佳答案

如果您需要一些约定俗成的东西,您可以使用 Albedo清空所有可写 IEnumerable<>特性。你可以从这样的事情开始:

public class EmtpyEnumerables : ReflectionVisitor<object>
{
private object value;

public EmtpyEnumerables(object value)
{
this.value = value;
}

public override object Value
{
get { return value; }
}

public override IReflectionVisitor<object> Visit(PropertyInfoElement propertyInfoElement)
{
var pi = propertyInfoElement.PropertyInfo;
if (pi.PropertyType.IsConstructedGenericType &&
pi.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
pi.CanWrite)
{
var elementType = pi.PropertyType.GetGenericArguments().Single();
pi.SetValue(value, Array.CreateInstance(elementType, 0));
return this;
}

return base.Visit(propertyInfoElement);
}
}

假设Foo看起来像这样:

public class Foo
{
public IEnumerable<Bar> Bars { get; set; }

public IEnumerable<Baz> Bazs { get; set; }

public IEnumerable<Qux> Quxs { get; set; }

public string Corge { get; set; }

public int Grault { get; set; }
}

然后下面的测试通过:

[Fact]
public void FillBarsZeroOutAllOtherSequences()
{
var fixture = new Fixture();

var actual = fixture.Create<Foo>();
new TypeElement(actual.GetType()).Accept(new EmtpyEnumerables(actual));
actual.Bars = fixture.CreateMany<Bar>();

Assert.NotEmpty(actual.Bars);
Assert.Empty(actual.Bazs);
Assert.Empty(actual.Quxs);
Assert.NotEqual(default(string), actual.Corge);
Assert.NotEqual(default(int), actual.Grault);
}

如果你觉得写出来太麻烦new TypeElement(actual.GetType()).Accept(new EmtpyEnumerables(actual)); ,我相信您可以想办法将其隐藏在辅助方法中。

关于c# - 单个对象创建时的 AutoFixture 自定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33913329/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com