Autofixture 声明性自动数据参数的属性集合大小
Collection size from attribute for Autofixture declarative autodata parameter
如何使用 属性 上的属性指定 list/enumerable 的 length/size 使用 Autofixture 的声明性参数样式传递到测试中?
我希望能够在不将参数移入测试主体的情况下使该测试通过。
[Theory, AutoData]
public void CollectionSizeTest(
List<int> defaultSize,
List<int> customSize,
List<int> customSize2,
IEnumerable<string> empty
)
{
Assert.Equal(3, defaultSize.Count);
Assert.Equal(5, customSize.Count);
Assert.Equal(6, customSize2.Count);
Assert.Empty(empty);
}
您可以为此创建自定义属性,例如 CollectionSizeAttribute
:
[Theory, AutoData]
public void CollectionSizeTest(
List<int> defaultSize,
[CollectionSize(5)] List<int> customSize,
[CollectionSize(6)] List<int> customSize2,
[CollectionSize(0)] IEnumerable<string> empty,
List<string> defaultSize2
)
{
Assert.Equal(3, defaultSize.Count);
Assert.Equal(5, customSize.Count);
Assert.Equal(6, customSize2.Count);
Assert.Empty(empty);
Assert.Equal(3, defaultSize2.Count);
}
public class CollectionSizeAttribute : CustomizeAttribute
{
private readonly int _size;
public CollectionSizeAttribute(int size)
{
_size = size;
}
public override ICustomization GetCustomization(ParameterInfo parameter)
{
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
var objectType = parameter.ParameterType.GetGenericArguments()[0];
var isTypeCompatible =
parameter.ParameterType.IsGenericType
&& parameter.ParameterType.GetGenericTypeDefinition().MakeGenericType(objectType).IsAssignableFrom(typeof(List<>).MakeGenericType(objectType))
;
if (!isTypeCompatible)
{
throw new InvalidOperationException($"{nameof(CollectionSizeAttribute)} specified for type incompatible with List: {parameter.ParameterType} {parameter.Name}");
}
var customizationType = typeof(CollectionSizeCustomization<>).MakeGenericType(objectType);
return (ICustomization) Activator.CreateInstance(customizationType, parameter, _size);
}
public class CollectionSizeCustomization<T> : ICustomization
{
private readonly ParameterInfo _parameter;
private readonly int _repeatCount;
public CollectionSizeCustomization(ParameterInfo parameter, int repeatCount)
{
_parameter = parameter;
_repeatCount = repeatCount;
}
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedBuilder(fixture.CreateMany<T>(_repeatCount).ToList()),
new EqualRequestSpecification(_parameter)
));
}
}
}
这会导致通过调用 fixture.CreateMany<T>(_repeatCount)
.
将参数创建为具有给定大小的列表
如何使用 属性 上的属性指定 list/enumerable 的 length/size 使用 Autofixture 的声明性参数样式传递到测试中?
我希望能够在不将参数移入测试主体的情况下使该测试通过。
[Theory, AutoData]
public void CollectionSizeTest(
List<int> defaultSize,
List<int> customSize,
List<int> customSize2,
IEnumerable<string> empty
)
{
Assert.Equal(3, defaultSize.Count);
Assert.Equal(5, customSize.Count);
Assert.Equal(6, customSize2.Count);
Assert.Empty(empty);
}
您可以为此创建自定义属性,例如 CollectionSizeAttribute
:
[Theory, AutoData]
public void CollectionSizeTest(
List<int> defaultSize,
[CollectionSize(5)] List<int> customSize,
[CollectionSize(6)] List<int> customSize2,
[CollectionSize(0)] IEnumerable<string> empty,
List<string> defaultSize2
)
{
Assert.Equal(3, defaultSize.Count);
Assert.Equal(5, customSize.Count);
Assert.Equal(6, customSize2.Count);
Assert.Empty(empty);
Assert.Equal(3, defaultSize2.Count);
}
public class CollectionSizeAttribute : CustomizeAttribute
{
private readonly int _size;
public CollectionSizeAttribute(int size)
{
_size = size;
}
public override ICustomization GetCustomization(ParameterInfo parameter)
{
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
var objectType = parameter.ParameterType.GetGenericArguments()[0];
var isTypeCompatible =
parameter.ParameterType.IsGenericType
&& parameter.ParameterType.GetGenericTypeDefinition().MakeGenericType(objectType).IsAssignableFrom(typeof(List<>).MakeGenericType(objectType))
;
if (!isTypeCompatible)
{
throw new InvalidOperationException($"{nameof(CollectionSizeAttribute)} specified for type incompatible with List: {parameter.ParameterType} {parameter.Name}");
}
var customizationType = typeof(CollectionSizeCustomization<>).MakeGenericType(objectType);
return (ICustomization) Activator.CreateInstance(customizationType, parameter, _size);
}
public class CollectionSizeCustomization<T> : ICustomization
{
private readonly ParameterInfo _parameter;
private readonly int _repeatCount;
public CollectionSizeCustomization(ParameterInfo parameter, int repeatCount)
{
_parameter = parameter;
_repeatCount = repeatCount;
}
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedBuilder(fixture.CreateMany<T>(_repeatCount).ToList()),
new EqualRequestSpecification(_parameter)
));
}
}
}
这会导致通过调用 fixture.CreateMany<T>(_repeatCount)
.