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



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

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

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

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

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

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

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

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

MAV说的是真的。另外,有一种方法可以将测试类从代码覆盖中排除。

只要用属性[ExcludeFromCodeCoverage]装饰你的[TestClass] !

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

是的,你可以,但首先你必须明白,当

  1. 期望的异常与你的函数抛出的异常匹配如

    assertThrows (NullPointerException.class()→userProfileService.getUserDetailById (userProfile.getAssociateId ()));

  2. 当预期异常和实际异常不匹配或assertthrow没有抛出任何异常时。考虑上面的场景示例,假设被调用的函数将抛出除NullPointerException之外的其他异常,那么assertthrow将失败。

现在你必须同时考虑assertthrow的失败和通过。

我找到的解是

userProfile = new UserProfile("101", "Amit Kumar Gupta", "amit@gmail.com", "Software Intern", "No",
                "999999999");
        userProfile2 = new UserProfile("102", "Satyam Sharma", "Satyam@gmail.com", "Software Engineer", "Yes",
                "8769356421");
        Mockito.when(userProfileDAO.findById(Mockito.anyString())).thenReturn(Optional.ofNullable(userProfile))
                .thenReturn(Optional.ofNullable(userProfile2));
List<Class<? extends Exception>> exceptionClassList = new ArrayList<Class<? extends Exception>>();
        exceptionClassList.add(NullPointerException.class);
        exceptionClassList.add(IllegalArgumentException.class);
        for (int i = 0; i < 2; i++) {
            try {
                assertThrows(exceptionClassList.get(i),
                        () -> userProfileService.getUserDetailById(userProfile.getAssociateId()));
            } catch (AssertionError e) {
                assertNotNull(e.getMessage());
            }
        }

在这种情况下,Mockito将返回两个值,这两个值都将被assertThrow中的函数调用使用,第一次assertThrow将匹配预期的异常,即NullPointerException.class

第二次assertThrow将失败,因为lambda函数不会抛出任何异常,但assertThrow预计会抛出一个IllegalArgumentException。

它生成AssertionError,因此将被catch块捕获。

现在你有100%的覆盖率

最新更新