gpt4 book ai didi

c# - AutoFixture CompositeDataAttribute 不适用于 PropertyDataAttribute

转载 作者:太空狗 更新时间:2023-10-29 20:17:12 24 4
gpt4 key购买 nike

我正在尝试基于此示例中的 CompositeDataAttribute 创建 AutoPropertyDataAttribute AutoFixture: PropertyData and heterogeneous parameters .

它对单组参数有效,但对更多参数组无效。这是代码:

public static IEnumerable<object[]> NumericSequence
{
get
{
yield return new object[] {1};
//yield return new object[] {2};
}
}

[Theory]
[AutoPropertyData("NumericSequence")]
public void Test(int? p1, int? p2, int? p3)
{
Assert.NotNull(p1);
Assert.NotNull(p2);
}

public class AutoPropertyDataAttribute : CompositeDataAttribute
{
public AutoPropertyDataAttribute(string propertyName)
: base(
new DataAttribute[] {
new PropertyDataAttribute(propertyName),
new AutoDataAttribute()
})
{
}
}

尝试取消注释第二个 yield 将中断测试并显示消息:

System.InvalidOperationException: Expected 2 parameters, got 1 parameters
at Ploeh.AutoFixture.Xunit.CompositeDataAttribute.<GetData>d__0.MoveNext()
at Xunit.Extensions.TheoryAttribute.<GetData>d__7.MoveNext()
at Xunit.Extensions.TheoryAttribute.EnumerateTestCommands(IMethodInfo method)

ClassDataAttribute 也是如此

最佳答案

我遇到了这个问题并决定实现一个自定义的 DataAttribute 来解决这个问题。我不能使用任何一个属性作为基类(原因如下)所以我只是从每个属性的源中获取我需要的东西。谢谢OSS :)

注意事项:

  • 我想稍微改变一下语义,这样我就可以选择生成单个对象而不是数组。只是让单对象参数的代码看起来更整洁。这意味着我不能将 PropertyDataAttribute 用作基类
  • 每次生成一组新参数时都需要创建夹具。这意味着我不能将 AutoDataAttribute 用作基类

Gist

或下面的内联源代码:

public class AutoPropertyDataAttribute : DataAttribute
{
private readonly string _propertyName;
private readonly Func<IFixture> _createFixture;

public AutoPropertyDataAttribute(string propertyName)
: this(propertyName, () => new Fixture())
{ }

protected AutoPropertyDataAttribute(string propertyName, Func<IFixture> createFixture)
{
_propertyName = propertyName;
_createFixture = createFixture;
}

public Type PropertyHost { get; set; }

private IEnumerable<object[]> GetAllParameterObjects(MethodInfo methodUnderTest)
{
var type = PropertyHost ?? methodUnderTest.DeclaringType;
var property = type.GetProperty(_propertyName, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);

if (property == null)
throw new ArgumentException(string.Format("Could not find public static property {0} on {1}", _propertyName, type.FullName));
var obj = property.GetValue(null, null);
if (obj == null)
return null;

var enumerable = obj as IEnumerable<object[]>;
if (enumerable != null)
return enumerable;

var singleEnumerable = obj as IEnumerable<object>;
if (singleEnumerable != null)
return singleEnumerable.Select(x => new[] {x});

throw new ArgumentException(string.Format("Property {0} on {1} did not return IEnumerable<object[]>", _propertyName, type.FullName));
}

private object[] GetObjects(object[] parameterized, ParameterInfo[] parameters, IFixture fixture)
{
var result = new object[parameters.Length];

for (int i = 0; i < parameters.Length; i++)
{
if (i < parameterized.Length)
result[i] = parameterized[i];
else
result[i] = CustomizeAndCreate(fixture, parameters[i]);
}

return result;
}

private object CustomizeAndCreate(IFixture fixture, ParameterInfo p)
{
var customizations = p.GetCustomAttributes(typeof (CustomizeAttribute), false)
.OfType<CustomizeAttribute>()
.Select(attr => attr.GetCustomization(p));

foreach (var c in customizations)
{
fixture.Customize(c);
}

var context = new SpecimenContext(fixture);
return context.Resolve(p);
}

public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
{
foreach (var values in GetAllParameterObjects(methodUnderTest))
{
yield return GetObjects(values, methodUnderTest.GetParameters(), _createFixture());
}
}
}

关于c# - AutoFixture CompositeDataAttribute 不适用于 PropertyDataAttribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18852608/

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