【问题标题】:What's the idiomatic way to verify collection size in xUnit?在 xUnit 中验证集合大小的惯用方法是什么?
【发布时间】:2017-10-09 19:19:10
【问题描述】:

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

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

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

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

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

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

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


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

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

【问题讨论】:

  • 如果您将stuffCollection.Count() 存储在一个单独的变量中并将其传递给断言,它是否会给您同样的错误?
  • 可能是this one?

标签: c# xunit xunit.net


【解决方案1】:

Xunit 为其大部分警告提供快速修复,因此您应该能够看到它认为“正确”的内容。

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

【讨论】:

  • 谢谢,这是有道理的。 FWIW,我在 VS Code 中构建时看到了这一点,其中没有显示快速操作,因此实际上在警告消息中包含修复建议会更有帮助。
  • @TomasLycken - 啊。是的,这里有一个问题:github.com/xunit/xunit/issues/1423
  • 我不喜欢这种行为;有时 1 计数只是偶然的,强制调用 .Single() 似乎不太具有表现力。测试可能会更改以期望不同的计数,并且必须进行更改以调用完全不同的方法而不是仅仅更改数字似乎很烦人。
  • Single 对单个 Item 来说很酷,我有 3 个 item,我不想写完整的 Assert.Collection,xUnit 有 Assert.Triple 吗?哈哈
  • @PawelCioch 根据xunit.net/xunit.analyzers/rules/xUnit2013.html 他们有EmptySingleNotEmpty - 如果您期望动态值 xUnit2013 不应该触发。
【解决方案2】:

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

【讨论】:

  • Assert.NotEmpty(result) 不是 Assert.Equal(2, result.Length) 的等价物,也不是 2 或更多项目,它测试的是不同的东西。
  • 同意,这是评论中的“Off by 1”错误。将 Assert.NotEmpty(result) 的注释从 2 修改为 1。
【解决方案3】:

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

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

var stuffCollection = GetSomeStuff();

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

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

就个人而言,我不是粉丝;这似乎是一种非常冗长的方式来说明您希望收藏多长时间。

【讨论】:

    【解决方案4】:

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

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

    并且投射它阻止了错误的出现。

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

    【讨论】:

    • 我很确定,这不是 ideomatic方式。
    • 可以也可以Assert.Equal(2, vm.Errors.Count() + 1) =)
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

      • 修复了这个问题,但您仍然没有像应有的那样使用 XUnit!
      • @DanielEisenreich 断言大于 1 的特定数字的计数的正确方法是什么?
      • @SomeGuyOnAComputer 和其他 4 个赞。忘记我说的话,我太厚脸皮了。如果它更大,你别无选择。
      猜你喜欢
      • 1970-01-01
      • 2019-12-26
      • 2016-05-01
      • 2015-09-20
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      相关资源
      最近更新 更多