【问题标题】:How do I obtain 100% coverage when an exception is thrown in a unit test?如何在单元测试中抛出异常时获得 100% 的覆盖率?
【发布时间】:2014-06-06 21:31:00
【问题描述】:

C# 中,您可以像这样在默认测试套件中捕获异常:

[TestMethod]
[ExpectedException(typeof (ArgumentNullException))]
public void TestNullComposite()
{
    IApi api = new Api();
    api.GetDataUsingDataContract(null); // this method throws ArgumentNullException
}

但是当你分析代码覆盖率时,它说你只得到了 66.67% 的覆盖率,因为最后一个花括号没有被覆盖。

我将如何在此单元测试中实现 100% 的覆盖率?

【问题讨论】:

  • 您应该分析测试覆盖的代码百分比。不自己测试(我什至不明白你的测试涵盖了什么)
  • 还请记住,行级别的覆盖率不是一个很好的指标,也不是重点。关键是,真正糟糕的事情发生的剩余风险是什么?
  • 这是否意味着,您有 UnitTests#2 来测试其他 UnitTests#1 并获得对这些 UnitTests#1 的 100% 覆盖?然后是另一组 UnitTests#3 以获得 100% 的 UnitTests#2 覆盖率?来吧...单元测试应该足够简单以至于它不需要测试本身。如果不是,那你就做错了。
  • 听起来编码标准与测试标准相矛盾。这只能通过使两者在同一地点和时间重合,从而导致相互湮灭或进一步的一系列会议,以更糟的为准来解决。
  • 好的,我理解所有认为 100% 测试代码覆盖率是愚蠢的火焰 - 但我个人认为大括号是你和 100% 测试代码覆盖率之间唯一存在的东西是愚蠢的。跨度>

标签: c# unit-testing


【解决方案1】:

通常当人们测量代码覆盖率时,他们查看的是测试覆盖的代码,而不是测试本身。

正如本例所示,要求100% 覆盖测试单元真的没有意义。

测试应该抛出。这就是您要测试的内容。

如果您真的希望执行整个方法,我想您可以测试是否手动抛出了异常。像这样的东西(还没有测试过,但我不明白为什么它不应该工作):

[TestMethod]
public void TestNullComposite()
{
    IApi api = new Api();
    bool didThrow = false;
    try
    {
        api.GetDataUsingDataContract(null); // this method throws ArgumentNullException
    }
    catch(ArgumentNullException) 
    {
        didThrow = true;
    }
    Assert.IsTrue(didThrow);
}

但这似乎是无缘无故的额外工作。我建议您重新评估您的测试实践。

【讨论】:

  • 好的,但是你没有 100% 的分支覆盖率。但我想你确实回答了基本假设 - 如果 Savanna 指出,100% 的测试代码覆盖率并不比 99% 好,没有 100% 的唯一原因是花括号。
  • 100% 不是您的测试所必需的。你已经拥有的很好。
【解决方案2】:

NUnit 中有一个方法Assert.Throws<Exception>(),它检查是否抛出了所需的异常。它还会将该异常作为返回值返回,以便您可以根据需要进行进一步的断言:

[Test]
public void Api_GetDataUsingDataContractWithNullParameter_ThrowsArgumentNullException()
{
    var api = new Api();
    var exception = Assert.Throws<ArgumentNullException>(() => api.GetDataUsingDataContract(null));
    Assert.That(exception.Message, Is.Not.Null.Or.Empty);
    Assert.That(exception.Message, Is.StringContaining("source"));
}

由于该方法不会自行抛出,因此您的覆盖率将是 100%。

【讨论】:

    【解决方案3】:

    MAV 说的是真的。此外,还有一种方法可以将测试类排除在代码覆盖范围之外。

    只需使用属性[ExcludeFromCodeCoverage] 装饰您的 [TestClass]!

    这样至少理论上可以达到100% CC。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-06
      • 2023-04-01
      • 2014-04-06
      • 2011-01-16
      • 1970-01-01
      • 2014-05-11
      • 2015-04-01
      • 2023-03-21
      相关资源
      最近更新 更多