【问题标题】:How to cover my logger in a catch clause in junit如何在junit的catch子句中覆盖我的记录器
【发布时间】:2018-10-09 15:12:35
【问题描述】:

我正在尝试对我的应用程序进行完整的 junit 测试,但在测试记录器消息时我被卡住了。

try {
    fillParameters(args);
} catch (ArgumentException e) {
    logger.error(e.getMessage(), e);
    return;
}

这里是触发异常的代码:

if (args.length > 3) {
    throw new ArgumentException("Wrong use of the command -> too many args"); 
}

一次测试:

@Test
public void testFillParametersWithTooManyArguments() {
    String[] args = { "...", "...", "...", "..." };
    Throwable e = null;
    try {
        testInstance.fillParameters(args);
    } catch (Throwable ex) {
        e = ex;
    }
    assertTrue(e instanceof ArgumentException); //this test is working as expected
}

当我查看代码覆盖率时,logger.error(e.getMessage(), e);部分未涵盖,我应该如何涵盖它?我想我必须模拟记录器?

【问题讨论】:

  • 但是如果你捕捉到异常,然后记录并返回,你的测试永远不会捕捉到异常。
  • 捕获而不是重新抛出会阻止调用者知道发生了错误。您可以记录,然后重新抛出原始错误。
  • @spi 不,不要。处理错误(例如通过记录),或者不捕获它,让调用者处理它。如果你两者都做,你可能会在这两个地方都做登录,这看起来像是有两个例外。
  • 此代码位于 main 方法中,我只想在触发此异常时停止进程并将我的异常记录在控制台中。有什么问题吗?我想测试我的 logger.error() 是否被调用并记录正确的消息。
  • 我正在使用 log4j,我试图模拟 appender 部分但我无法成功。编辑:nvm 我认为这里最好的方法是抛出我的异常并测试是否抛出异常

标签: java logging junit mockito


【解决方案1】:

简答题
测试你真正想要测试的代码。

一些信息
您的示例单元测试中的代码绝不会测试您的第一个代码块中的代码。 我假设因为它看起来像 Java 代码并且问题被标记为 Java 问题,所以第一个代码块中的代码实际上是在某个方法中。 您必须统一该方法以在该方法的异常捕获块中获得测试覆盖率。

例如:

public void IHateToTellPeopleMyMethodName(final String[] args)
{
    try
    {
        fillParameters(args);
    }
    catch (ArgumentException e)
    {
        logger.error(e.getMessage(), e);
        return;
    }
}

为了获得 catch 块中的测试覆盖率 IHateToTellPeopleMyMethodName 方法, 你必须测试 IHateToTellPeopleMyMethodName 单元测试中的方法。

这个单元测试方法对IHateToTellPeopleMyMethodName 方法没有任何作用,因为它不调用IHateToTellPeopleMyMethodName 方法。

@Test
public void testThatInNoWayTestsTheIHateToTellPeopleMyMethodNameMethod()
{
    String[] args = { "...", "...", "...", "..." };

    try
        {
        testInstance.fillParameters(args);
                fail("expected exception not thrown");
    }
        catch (Throwable ex)
        {
            assertTrue(e instanceof ArgumentException);
    }
}

与上面的单元测试代码不同, 本单元测试涵盖IHateToTellPeopleMyMethodName 方法。

@Test
public void testTheIHateToTellPeopleMyMethodNameMethod()
{
    String[] args = { "...", "...", "...", "..." };

    testInstance.IHateToTellPeopleMyMethodName(args);

          verify(mockLogger).error(
                eq(EXPECTED_MESSAGE_TEXT),
                    any(ArgumentException.class));
}

编辑备注
我的错, any() 需要一个 class 对象作为参数, 不是类名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多