在单元测试中抛出异常时,如何获得100%的覆盖率?

时间:2014-06-06 21:31:00

标签: c# unit-testing

C#中,您可以在默认测试套件中捕获异常,如下所示:

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

但是当您分析代码覆盖率时,它表示您只获得66.67%的覆盖率,因为最后一个大括号没有被覆盖。

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

3 个答案:

答案 0 :(得分:6)

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

正如本案所示,要求 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);
}

但似乎没有充分理由的额外工作。我建议你重新评估你的测试实践。

答案 1 :(得分:3)

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%。

答案 2 :(得分:1)

MAV说的是真的。此外,还有一种方法可以从代码覆盖率中排除测试类的分析。

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

这种方式至少在理论上可以达到100%CC。