繁体   English   中英

如何在xunit / autofixture中组合PropertyData和AutoNSubstituteData属性?

[英]How to combine PropertyData and AutoNSubstituteData attributes in xunit/autofixture?

我正在使用[AutoNSubstituteData]属性,该属性已在此处发布:

AutoFixture,xUnit.net和Auto Mocking

我想将它与xunit扩展的[PropertyData("")]属性结合起来。

这是我的测试:

public static IEnumerable<string[]> InvalidInvariant
{
    get
    {
        yield return new string[] { null };
        yield return new [] { string.Empty };
        yield return new [] { " " };
    }
}

[Theory, AutoNSubstituteData, PropertyData("InvalidInvariant")]
public void TestThatGuardsAreTriggeredWhenConnectionStringArgumentIsInvalid(
    IDeal deal,
    IDbConnection conn,
    IDb db,
    ISender sender,
    string invalidConnString,
    string query)
{
    deal.Init.Group.Returns(Group.A);
    deal.Aggr.Group.Returns(Group.A);
    deal.Product.Commodity.Returns(Product.Commodity.E);

    var sut = new Handler(db, sender);
    Assert.Throws<ArgumentException>(() => 
        sut.HandleDeal(deal, conn, invalidConnString, query));
}

有没有办法组合这些属性或获得所需的功能(模拟一切,除了invalidConnstring ,应该用属性数据填充)?

[Theory]属性通过查找一个或多个'数据源属性'来工作; 例如

  • [InlineData]
  • [PropertyData]
  • [ClassData]
  • 等等

[AutoData]属性只是另一个这样的属性,派生的[AutoNSubstituteData]属性也是如此。

可以将相同的[Theory]添加多个“数据源属性”,这可以通过[InlineData]属性的惯用使用来[InlineData]

[Theory]
[InlineData("foo")]
[InlineData("bar")]
[InlineData("baz")]
public void MyTest(string text)

这产生了三个测试用例。

也可以组合[PropertyData][AutoData] ,但它可能不会做你想做的事情 这个:

[Theory]
[AutoNSubstituteData]
[PropertyData("InvalidInvariant")]
public void MyTest(/* parameters go here */)

将导致1 + n个测试用例:

  • 来自[AutoNSubstituteData] 1个测试用例
  • 来自InvalidInvariant属性的n个测试用例

这两个属性对彼此一无所知,所以你不能将它们组合起来,因为它们彼此了解。

但是,当您实现一个属性时,您可以编写您想要的任何代码,包括使用Fixture实例,那么为什么不这样做呢?

public static IEnumerable<string[]> InvalidInvariant
{
    get
    {
        var fixture = new Fixture().Customize(new MyConventions());
        // use fixture to yield values...,
        // using the occasional hard-coded test value
    }
}

另一种选择是使用来自InlineAutoDataAttribute派生,这将使您能够像这样编写测试用例:

[Theory]
[MyInlineAutoData("foo")]
[MyInlineAutoData("bar")]
[MyInlineAutoData("baz")]
public void MyTest(string text, string someOtherText, int number, Guid id)

这将导致第一个参数( text )用属性中的常量填充,而其余参数由AutoFixture填充。

从理论上讲,您也可以使用CompositeDataAttribute [AutoData][PropertyData]属性,但它可能无法按照您的喜好工作

最后,您可以考虑使用Exude进行真正的一流参数化测试。

有两种方法可以做到这一点:

选项1 - 使用AutoFixture.Xunit和CompositeDataAttribute类:

internal class AutoNSubstituteDataAttribute : AutoDataAttribute
{
    internal AutoNSubstituteDataAttribute()
        : base(new Fixture().Customize(new AutoNSubstituteCustomization()))
    {
    }
}

internal class AutoNSubstitutePropertyDataAttribute : CompositeDataAttribute
{
    internal AutoNSubstitutePropertyDataAttribute(string propertyName)
        : base(
            new DataAttribute[] { 
                new PropertyDataAttribute(propertyName), 
                new AutoNSubstituteDataAttribute() })
    {
    }
}

定义测试用例如下:

public class Scenario
{
    public static IEnumerable<object[]> InvalidInvariantCase1
    {
        get
        {
            yield return new string[] { null };
        }
    }

    public static IEnumerable<object[]> InvalidInvariantCase2
    {
        get
        {
            yield return new string[] { string.Empty };
        }
    }

    public static IEnumerable<object[]> InvalidInvariantCase3
    {
        get
        {
            yield return new string[] { " " };
        }
    }
}

然后将参数化测试声明为:

public class Scenarios
{
    [Theory]
    [AutoNSubstitutePropertyData("InvalidInvariantCase1")]
    [AutoNSubstitutePropertyData("InvalidInvariantCase2")]
    [AutoNSubstitutePropertyData("InvalidInvariantCase3")]
    public void AParameterizedTest(
        string invalidConnString,
        IDeal deal,
        IDbConnection conn,
        IDb db,
        ISender sender,
        string query)
    {
    }
}

请注意,参数化参数invalidConnString必须在其他参数之前声明

选项2 - 使用Exude

public class Scenario
{
    public void AParameterizedTest(
        IDeal deal,
        IDbConnection conn,
        IDb db,
        ISender sender,
        string invalidConnString,
        string query)
    {
    }

    [FirstClassTests]
    public static TestCase<Scenario>[] RunAParameterizedTest()
    {
        var testCases = new [] 
        {
            new 
            {
                invalidConnString = (string)null
            },
            new
            {
                invalidConnString = string.Empty
            },
            new
            {
                invalidConnString = " "
            }
        };

        var fixture = new Fixture()
            .Customize(new AutoNSubstituteCustomization());

        return testCases
            .Select(tc =>
                new TestCase<Scenario>(
                    s => s.AParameterizedTest(
                        fixture.Create<IDeal>(),
                        fixture.Create<IDbConnection>(),
                        fixture.Create<IDb>(),
                        fixture.Create<ISender>(),
                        tc.invalidConnString,
                        fixture.Create<string>())))
            .ToArray();
    }
}

我已经实现了一个AutoPropertyDataAttribute ,它将xUnit的PropertyDataAttribute与AutoFixture的AutoDataAttribute相结合。 我在这里发布了答案。

在您的情况下,您将需要以与从AutoDataAttribute相同的方式继承属性,除了您传递夹具创建函数而不是实例:

public class AutoNSubPropertyDataAttribute : AutoPropertyDataAttribute
{
    public AutoNSubPropertyDataAttribute(string propertyName)
        : base(propertyName, () => new Fixture().Customize(new AutoNSubstituteCustomization()))
    {
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM