将字符串数组传递给xUnit测试方法

67
我想将一个字符串数组传递给我的XUnit测试方法,但当我只是按照以下方式进行时它无法工作(使用数组+参数机制)。
    [Theory]
    [InlineData(new object[] { "2000-01-02", "2000-02-01" })]
    public void TestSynchronizeMissionStaffing_PeriodNoMatch(string[] dateStrings)

我可以这样解决这个问题:

    [Theory]
    [InlineData(0, new object[] { "2000-01-02", "2000-02-01" })]
    public void TestSynchronizeMissionStaffing_PeriodNoMatch(int dummy, string[] dateStrings)

但我希望有更好的解决方法来解决这个问题。

你能告诉我吗?


数组中的字符串数量可能是任意的。 - Serge Intern
这已经是2018年了,但这仍然是唯一对我有效的解决方法。应该为xUnit开放一个问题报告。 - yair
修正最后一条评论为“曾经是唯一的解决方法”。事实上,似乎有一个简单的解决方案 - yair
8个回答

74

在方法的string[]参数之前使用params,然后您就不需要在InlineData属性中初始化string[],而是可以使用可变数量的string字面量,编译器不会抱怨:

[Theory]
    [InlineData("2000-01-02", "2000-02-01")]
    public void TestSynchronizeMissionStaffing_PeriodNoMatch(params string[] dateStrings)

2
我该如何传递一个空集合? - Renato Pereira
1
@renatogbp 使用yair的解决方案,你只需要添加另一个内联[InlineData()]。这将在测试调用时创建一个空数组。 - Itanex

46

为了搜索者的好处-在2020年,这是可以实现的,而不需要paramsobject转换。

让它正常运行的关键似乎是在编写InlineData部分之前编写方法签名。下面是一些可行的代码:

[Theory]
[InlineData(true, "expected", new string[] { "expected", "another" })]
[InlineData(false, "nope!", new string[] { "expected", "another" })]
public async void StringCheck_WithInputs_ExpectResultsMatch(bool expectedResult, string expectedString, string[] possibleStrings)
{
    bool actualResult = false;

    foreach(var row in possibleStrings)
    {
        if(row == expectedString)
        {
            actualResult = true;
        }
    }

    Assert.Equal(expectedResult, actualResult);
}

7
实际上,当你只有一个参数(数组)时,它不起作用,但当你有多个参数和一个以上的数组时,它就可以正常工作。 - Jacob
3
更新(xunit 2.4.1 / xunit.runner.visualstudio 2.4.2):现在只需使用数组参数@Jacob即可正常工作。 - Maicon Heck
3
@MaiconHeck,Jacob所说的似乎仍然正确。我正在使用_xunit 2.4.1_和_xunit.runner.visualstudio 2.4.3_,除非我使用某些基本参数启动InlineData()属性,否则visual studio会发出警告。 - Sal Alturaigi
4
@MattM - 他们通过在前面加入一个假属性来使其正常工作,例如 public void MyTest(int iLiterallyDoNotCare, string [] importantArray)[InlineData(666, new string [] { "Puppies", "Kittens" })] - Red
1
这个帮了我很多忙!我一直在想为什么它在一个方法上能够工作而在另一个方法上却不能。 - ladygargar
显示剩余2条评论

8

这应该可以工作

[Theory]
[InlineData(new object[] { new string[] { "2000-01-02", "2000-02-01" } })]
public void TestSynchronizeMissionStaffing_PeriodNoMatch(string[] dateStrings)

当您像所示一样初始化对象数组时,它的所有元素都是单个对象。因此,当您尝试将字符串数组作为参数传递时,它会传递对象数组的第一个元素,即"2000-01-02"。


这是正确的答案,你可以在GitHub上的这个问题中阅读到:https://github.com/xunit/xunit/issues/2060 - Daniel Lobo

5

这是C#中的params特性,可以扩展数组。因此,xunit无法将其传递给您的一个参数,您可以将数组强制转换,例如:

[InlineData((object)(new object[] { "2000-01-02", "2000-02-01" }))] 参见这里


对我来说可以运行...你想分享一个Gist/Repo吗? - robi-y
我已经附上了一张截图,显示数组已被传递。 - robi-y
我使用VS Studio 2015社区版,Resharper 10.2和XUnit 2.1.0。你知道为什么我们会得到不同的行为吗? - Serge Intern
还没有尝试过这个环境。一些相关问题请参考:https://github.com/xunit/xunit/issues/763,你可能想在那里讨论。感谢您的支持,请在发现任何问题时更新。 - robi-y

3

0
每当你需要将字符串数组作为参数传递给你的测试时,你可以使用你的代码,只需在字符串数组前加上 "params" 关键字即可。它能够正常工作。
[Theory]
[InlineData(new object[] { "2000-01-02", "2000-02-01" })]
public void TestSynchronizeMissionStaffing_PeriodNoMatch(params string[] dateStrings)
{
   //Assert.[YourVerifier]();
}

0

0
我正在使用Xunit版本2.4.1,并参考上面的ChrisCa的答案。我能够简单地按照下面的方式进行操作,这样数据就可以与测试分开。

public class NoGenTests
{
    [Theory]
    [MemberData(nameof(NoGenTestsData.Nos), MemberType = typeof(NoGenTestsData))]
    public void NoGenTest(int size, int[] nos)

    {
         /*
        foreach (var item in nos)
        {
            Console.WriteLine("Item is " + item);
        }*/
        Assert.Equal(size, nos.Length);
    }

}

public class NoGenTestsData
{

    public static object[] Nos =
    {
            new object[] {3, new int[] {2, 3, 5}},
            new object[] {6, new int[] {2, 3, 5, 7, 11, 13}},
            new object[] {7, new int[] {2, 3, 5, 7, 11, 13, 17}},
            new object[] {8, new int[] {2, 3, 5, 7, 11, 13, 17, 19}},
            new object[] {2, new int[] {2, 3}},
            new object[] {1, new int[] {2}}
        };
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接