在单元测试中循环

Sha*_*aju 18 c# ienumerable nunit unit-testing for-loop

我们可以在单元测试中使用循环吗?

我的方法返回一个IEnumerable<IEnumerable>,我想在IEnumerable<IEnumerable>创建它的地方单元测试这个逻辑.基本上我想测试一下元素的数量IEnumerable是否符合预期.

我没有找到另一种方法来测试内部IEnumerable而没有循环语句.如果这是一个很好的做法,请告诉我.

Ale*_*ork 26

没有技术理由你不能这样做.您可以在单元测试中使用多个Assert语句.在循环中使用Assert语句只是在测试中使用多个Assert语句的简便方法.

但是,有些人认为在单元测试中应该只有一个Assert语句.

我个人不同意 - 我认为测试应该测试一件事 - 为了做到这一点,有时您可能需要多个Assert语句.

如果你的方法返回一个IEnumerable的产品,并且每个产品包含一个IEnumerable of Color,那么我认为以下测试是好的:

[Test]
public void All_products_should_have_some_colors()
{
    var products = GetProducts();

    foreach (var product in products)
    {
        Assert.IsNotEmpty(product.Colors);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,您需要注意,如果IEnumerable包含0个元素,则循环将永远不会执行任何Assert语句,并且您的单元测试将"通过" - 而您可能原本希望它失败.

为了解决这种情况,你可以进行单独的测试,确保IEnumerable中有超过0个元素(即GetProducts确实返回了一些产品):

Assert.IsNotEmpty(products);
Run Code Online (Sandbox Code Playgroud)

  • 我认为我的答案中的测试是"可接受的",原因如下:1)它测试"单一的东西"(所有产品都有一些颜色).2)它简单易读. (2认同)
  • 我很少在测试中有多个Assert语句.但有时我确实有多个Asserts,或循环中的Assert.当我这样做时,我不会失眠.如果测试达到目的并且编写良好 - 那么我将继续下一个任务:-) (2认同)
  • 好的油漆.你可以制作几个断言语句,但只能做一件事.最好的例子是声明返回对象的所有属性都是正确的.但是如果我使用多个断言,我通常会将它们提取到私有方法,并小心给它一个有意义的名称,如AssertThatReturmedAdressObjectHasCorrectProperties. (2认同)

Gro*_*ile 8

避免在测试中编写循环的一个原因是一目了然地使测试简洁易读.由于您已使用NUnit标记了问题,并且您说您只想测试元素计数是否符合预期,请考虑使用NUnit约束来生成断言.

例如,

IEnumerable<IEnumerable<char>> someStrings = new[] { "abc", "cat", "bit", "hat" };

Assert.That(someStrings, Has.All.With.Length.EqualTo(3).And.All.Contains("a"));
Run Code Online (Sandbox Code Playgroud)

失败的消息:

预期:所有项目属性长度等于3和所有项目字符串包含"a"但是:<"abc","cat","bit","hat">

但如果你将"位"改为"蝙蝠",则通过.

本书xUnit测试模式:重构测试代码作者:Gerard Meszaros

对你这样的问题有很多很好的答案.