在xUnit中验证集合大小的惯用方法是什么?

Tom*_*han 83 c# xunit xunit.net

我在我的测试套件中有一个类似这样的测试:

[Fact]
public void VerifySomeStuff()
{
    var stuffCollection = GetSomeStuff();

    Assert.Equal(1, stuffCollection.Count());
}
Run Code Online (Sandbox Code Playgroud)

这个测试按照我的预期工作,但是当我运行它时xUnit会输出一个警告:

警告xUnit2013:不要使用Assert.Equal()来检查集合大小.

但是,警告中没有建议替代方案,谷歌搜索会将我带到xUnit中的源代码,以便验证是否打印了此警告.

如果Assert.Equal()不是验证集合长度的正确方法,那是什么?


澄清一下:我意识到我可以通过例如提取变量或使用Assert.True(stuff.Count() == 1)替代来"欺骗"xUnit而不发出此警告.后者只是hacky,而前者感觉就像xUnit试图避免多次迭代一样IEnumerable<T>,那么这是错误的方法(因为我会分别得到编译器提示,如果这是一个问题),并且xUnit本身不应该多次评估输入(事实上,无论变量提取如何,它都可能获得相同的输入,因为C#函数调用的工作方式).

所以,我不仅仅想从我的输出中删除该警告.我的问题的答案也解释了为什么首先将警告包含在库中,以及为什么我应该使用的方法更好.

vcs*_*nes 89

Xunit为其大多数警告提供快速修复,因此您应该能够看到它认为"正确"的内容.

的xUnit

在您的情况下,它希望您使用,Assert.Single因为您只期望一个项目.如果你断言任意数字,比如412,那么它就不会给你一个关于使用的警告Count.它只会建议使用,Single如果您期望一个项目,或者Empty如果您不期望任何项目.

  • 谢谢,这是有道理的.FWIW,我在VS Code中构建时看到了这一点,快速操作没有出现,所以实际上包含警告消息中的修复建议会更有帮助. (5认同)
  • 我不喜欢这种行为;有时1计数只是偶然的,并且强制执行对.Single()的调用似乎不太具有表达能力。该测试可能会更改以期望获得不同的计数,而不得不进行更改以调用完全不同的方法而不是仅更改数字似乎很烦人。 (4认同)
  • @TomasLycken - 啊.是的,这里有一个问题:https://github.com/xunit/xunit/issues/1423 (2认同)
  • Single 对于单个 Item 来说很酷,我有 3 个项目,并且我不想编写完整的 Assert.Collection,xUnit 有 Assert.Triple 吗?哈哈 (2认同)

Tik*_*all 23

该规则仅在测试集合中的 0 或 1 个项目时适用。

Assert.Equal(0, result.Length) // rule warning, use .Empty
Assert.Equal(1, result.Length) // rule warning, use .Single
Assert.Equal(2, result.Length) // ok
Run Code Online (Sandbox Code Playgroud)

满足规则:

Assert.Empty(result); // for 0 items
Assert.Single(result); // for 1 item
Assert.NotEmpty(result); // for 1 or more items
Run Code Online (Sandbox Code Playgroud)

当使用 Assert.NotEmpty 时,我们最好用计数来精确

Assert.Equal(2, result.Length) // Does not violate rule xUnit2013
Run Code Online (Sandbox Code Playgroud)

https://xunit.net/xunit.analyzers/rules/xUnit2013


jnn*_*nnn 6

如果您有多个项目,则无法使用 Assert.Single。

期望似乎是你应该使用Assert.Collection

var stuffCollection = GetSomeStuff();

Assert.Collection(stuffCollection, 
    item => Assert.True(true), // this lambda verifies the first item
    item => Assert.True(true), // second item
);
Run Code Online (Sandbox Code Playgroud)

上面的断言验证了集合中恰好有两个项目。您可以提供更严格的 lambda(例如,item => Assert.Equals(7, item.property1)如果需要,可以为每个项目提供更严格的 lambda)。

就我个人而言,我不是粉丝;这似乎是一种非常冗长的方式来表达你想要的集合有多长。