AutoFixture将PropertyData与多个条目和AutoData混合(使用AutoMoqCustomization) [英] AutoFixture mixing PropertyData with multiple entries and AutoData (using AutoMoqCustomization)

查看:62
本文介绍了AutoFixture将PropertyData与多个条目和AutoData混合(使用AutoMoqCustomization)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看过这两个类似的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?

编辑 这是异常堆栈跟踪:

EDIT Here'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:

  1. xUnit.net通过非通用,无类型的数组对参数化测试进行建模的方式
  2. 真正使这些测试用例看起来像二等公民的基于属性的模型
  3. 带有所有这些类型声明和大括号的语言带来的噪音

对于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)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆