问题描述
我已经看过这两个类似的SO问题:
I've looked at both of these similar SO questions:
- AutoFixture: PropertyData and heterogeneous parameters
- AutoFixture CompositeDataAttribute does not work with PropertyDataAttribute
他们很棒,让我快到了.但是两个示例都只在发出的IEnumerable PropertyData中使用一个条目(即:yield return new object[] { 2, 4 };
-请参阅: https://stackoverflow.com/a/16843837/201308 )可以正常工作,但是每当我要对多个对象[]测试数据进行测试时,它都会爆炸.我有一整套要发送的测试数据.
And they're awesome and get me nearly there. But both examples use only one entry in the emitted IEnumerable PropertyData (i.e.: yield return new object[] { 2, 4 };
-- see: https://stackoverflow.com/a/16843837/201308) This works, but it blows up whenever I want to do test over more than one object[] test data. I have a whole collection of test data I want to send.
我在想答案( https://stackoverflow.com/a/19309577/201308 )是类似于我所需要的,但我无法弄清楚.我基本上需要AutoFixture为PropertyData的每次迭代创建一个sut
实例.
I'm thinking the answer here (https://stackoverflow.com/a/19309577/201308) is similar to what I need, but I can't figure it out. I basically need AutoFixture to create a sut
instance for each iteration of the PropertyData.
一些参考:
public static IEnumerable<object[]> TestData
{
get
{
// totally doesn't work
return new List<object[]>()
{
new object[] { new MsgData() { Code = "1" }, CustomEnum.Value1 },
new object[] { new MsgData() { Code = "2" }, CustomEnum.Value2 },
new object[] { new MsgData() { Code = "3" }, CustomEnum.Value3 },
new object[] { new MsgData() { Code = "4" }, CustomEnum.Value4 },
};
// totally works
//yield return new object[] { new MsgData() { Code = "1" }, CustomEnum.Value1 };
}
}
返回列表将导致预期3个参数,得到2个参数"异常.如果我只返回单个yield语句,它就可以工作. (我还尝试遍历列表并产生每个项目-没什么区别,这很有意义,因为它与返回完整列表几乎完全一样.)
Returning the list results in a "Expected 3 parameters, got 2 parameters" exception. If I just return the single yield statement, it works. (I've also tried looping over the list and yielding each item -- no difference, which makes sense, seeing how it's pretty much the exact same thing as returning the full list.)
xUnit测试方法:
xUnit test method:
[Theory]
[AutoMoqPropertyData("TestData")]
public void ShouldMapEnum(MsgData msgData, CustomEnum expectedEnum, SomeObject sut)
{
var customEnum = sut.GetEnum(msgData);
Assert.Equal(expectedEnum, customEnum);
}
AutoMoqPropertyData
实现:
public class AutoMoqPropertyDataAttribute : CompositeDataAttribute
{
public AutoMoqPropertyDataAttribute(string dataProperty)
: base(new DataAttribute[]
{
new PropertyDataAttribute(dataProperty),
new AutoDataAttribute(new Fixture().Customize(new AutoMoqCustomization()))
})
{ }
}
我想念什么?当需要对PropertyData数据进行多次迭代时,是否可以同时混合PropertyData和AutoData驱动的AutoFixture属性?
What am I missing? Can I mix both PropertyData- and AutoData-driven AutoFixture attributes like this when wanting multiple iterations of the PropertyData data?
编辑这是异常堆栈跟踪:
EDITHere's the exception stack trace:
System.InvalidOperationException: Expected 3 parameters, got 2 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)
Result StackTrace:
at Xunit.Extensions.TheoryAttribute.<>c__DisplayClass5.<EnumerateTestCommands>b__1()
at Xunit.Extensions.TheoryAttribute.LambdaTestCommand.Execute(Object testClass)
推荐答案
您必须按照此答案鲁宾·巴特林克(Ruben Bartelink)指出了.
You have to supply the test cases as described in this answer that Ruben Bartelink points out.
[Theory]
[AutoMoqPropertyData("Case1")]
[AutoMoqPropertyData("Case2")]
[AutoMoqPropertyData("Case3")]
[AutoMoqPropertyData("Case4")]
public void ShouldMapEnum(
MsgData msgData, CustomEnum expectedEnum, SomeObject sut)
{
var customEnum = sut.GetEnum(msgData);
Assert.Equal(expectedEnum, customEnum);
}
public static IEnumerable<object[]> Case1 { get {
yield return new object[] {
new MsgData { Code = "1" }, CustomEnum.Value1 }; } }
public static IEnumerable<object[]> Case2 { get {
yield return new object[] {
new MsgData { Code = "2" }, CustomEnum.Value2 }; } }
public static IEnumerable<object[]> Case3 { get {
yield return new object[] {
new MsgData { Code = "3" }, CustomEnum.Value3 }; } }
public static IEnumerable<object[]> Case4 { get {
yield return new object[] {
new MsgData { Code = "4" }, CustomEnum.Value4 }; } }
但是,由于以下原因,该问题往往更普遍(而不是特定):
However, the problem tends to be more generic (rather than specific) because of:
- xUnit.net通过非通用,无类型的数组对参数化测试进行建模的方式
- 真正使这些测试用例看起来像二等公民的基于属性的模型
- 带有所有这些类型声明和大括号的语言带来的噪音
对于1.
和2.
以及用于参数化测试的现有xUnit.net模型,没有什么可做的.
For 1.
and 2.
and the existing xUnit.net model for parameterized tests there is not much left to do.
对于3.
,如果代码是用F#编写的,则大多数类型声明噪音(和一些大括号)都会消失:
For 3.
if the code is written in F# most of type declaration noise (and a few curly brackets) go away:
let Case1 : seq<obj[]> = seq {
yield [| { Code = "1" }; Value1 |] }
let Case2 : seq<obj[]> = seq {
yield [| { Code = "2" }; Value2 |] }
let Case3 : seq<obj[]> = seq {
yield [| { Code = "3" }; Value3 |] }
let Case4 : seq<obj[]> = seq {
yield [| { Code = "4" }; Value4 |] }
[<Theory>]
[<AutoMoqPropertyData("Case1")>]
[<AutoMoqPropertyData("Case2")>]
[<AutoMoqPropertyData("Case3")>]
[<AutoMoqPropertyData("Case4")>]
let ShouldMapEnum (msgData, expected, sut : SomeObject) =
let actual = sut.GetEnum(msgData)
Assert.Equal(expected, actual.Value)
以下是用于通过测试的类型:
Below are the types used to pass the test:
type MsgData = { Code : string }
[<AutoOpen>]
type Custom = Value1 | Value2 | Value3 | Value4
type SomeObject () =
member this.GetEnum msgData =
match msgData.Code with
| "1" -> Some(Value1)
| "2" -> Some(Value2)
| "3" -> Some(Value3)
| "4" -> Some(Value4)
| _ -> None
[<AttributeUsage(AttributeTargets.Field, AllowMultiple = true)>]
type AutoMoqPropertyDataAttribute (dataProperty) =
inherit CompositeDataAttribute(
PropertyDataAttribute(dataProperty),
AutoDataAttribute())
这篇关于AutoFixture将PropertyData与多个条目和AutoData混合(使用AutoMoqCustomization)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!