我正在尝试根据此示例
AutoFixture: PropertyData and heterogeneous parameters中的CompositeDataAttribute创建AutoPropertyDataAttribute.
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也是如此
解决方法
实际发生了什么
NumericSequence [PropertyData]定义了两次迭代.
NumericSequence [PropertyData]与[AutoData]的组合假定每次迭代都有足够的数据.
但是,实际的构成是:
1st iteration: [PropertyData],[AutoData] 2nd iteration: [PropertyData],[n/a]
这就是为什么在第二次迭代中你最终会耗尽数据.
组成
CompositeDataAttribute在某种意义上尊重LSP,它是根据所有数据理论DataAttribute类编程的.
(也就是说,没有假设所有属性都在最后用[AutoData]组成.)
因此,它不能简单地从第二次迭代跳转到第一次迭代并获取一些[AutoData]值 – 这将破坏LSP.
你能做什么
使实际构图看起来像:
1st iteration: [PropertyData],[AutoData]
通过定义两个属性:
public static IEnumerable<object[]> FirstPropertyData { get { yield return new object[] { 1 }; } } public static IEnumerable<object[]> OtherPropertyData { get { yield return new object[] { 9 }; } }
然后,原始测试可以写成:
[Theory] [AutoPropertyData("FirstPropertyData")] [AutoPropertyData("OtherPropertyData")] public void Test(int n1,int n2,int n3) { }
测试执行两次,n1始终由[PropertyData]提供,而n2和n3始终由[AutoData]提供.