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

What's the idiomatic way to verify collection size in xUnit?

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

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

    Assert.Equal(1, stuffCollection.Count());
}

这个测试按我预期的那样工作,但是当我 运行 它 xUnit 打印警告:

warning xUnit2013: Do not use Assert.Equal() to check for collection size.

但是,警告中没有建议任何替代方案,google 搜索将我带到 xUnit 中的源代码以进行验证打印此警告的测试。

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


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

所以,我不仅对从我的输出中删除该警告感兴趣。我的问题的答案还解释了 为什么 警告首先包含在库中,为什么 我应该使用的任何方法都更好。

Xunit 为其大部分警告提供了快速修复,因此您应该能够看到它认为是什么 "right"。

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

我在 xUnit 中使用 Count 属性 时遇到了同样的问题。

之后,我在集合上使用 Count() 函数,它解决了我的问题。

我发现这给了我同样的错误:

Assert.Equal(2, vm.Errors.Count());

并且转换它阻止了错误的出现。

Assert.Equal(2, (int)vm.Errors.Count());

对于列表中的单个元素,最好改用它: Assert.Single(resultList);

如果您有不止一项,则不能使用 Assert.Single。

您似乎应该使用 Assert.Collection:

var stuffCollection = GetSomeStuff();

Assert.Collection(stuffCollection, 
    item => true, // this lambda verifies the first item
    item => true, // second item
);

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

就个人而言,我不是粉丝;这似乎是一种非常冗长的方式来表达您希望 collection 持续多长时间。

该规则仅适用于测试集合中的 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

满足规则:

Assert.Empty(result); // for 0 items
Assert.Single(result); // for 1 item
Assert.NotEmpty(result); // for 1 or more items

当使用Assert.NotEmpty时,我们不妨用一个计数来精确

Assert.Equal(2, result.Length) // Does not violate rule xUnit2013

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