【问题标题】:Best way to test a method containing a try/catch block in JUnit在 JUnit 中测试包含 try/catch 块的方法的最佳方法
【发布时间】:2021-08-26 14:49:31
【问题描述】:

我有以下方法。该方法使用 Jackson ObjectMapper 转换 json 字符串的内容。如果 json 格式错误,则会打印堆栈跟踪并将对象设置为 null:

public ObjectTransferData extractJacksonObjectsFromFile(String json) {
  ObjectTransferData objectTransferData;
  try {
    objectTransferData = objectMapper.readValue(json, ObjectTransferData.class);
  } catch (Exception e) {
    e.printStackTrace();
    objectTransferData = null;
  }
  return objectTransferData;
}

我为可能的格式错误的 json 字符串编写了 JUnit 单元测试,如下所示:

@Test
public void testExtractJacksonObjectsFromFile_malformedJson_expectNull(){
  String malformedJson = "{";
  ObjectTransferData result = myService.extractJacksonObjectsFromFile(malformedJson);
  assertNull(result);
}

此测试通过。但它也将e.printStackTrace() 打印到我的终端中,这在测试执行期间掩盖了实际的重要日志。测试执行的读者可能会感到困惑。

我想知道如何解决这个问题。我想出了这些想法:

  1. 删除 try/catch 并抛出异常。这将允许我像这样编写测试,而不是在控制台中获取堆栈跟踪。
@Test
public void testExtractJacksonObjectsFromFile_malformedJson_expectException(){
  String malformedJson = "{";
  assertThrows(Exception.class, () ->
        objectImportService.extractJacksonObjectsFromFile(malformedJson)
  );
}

但缺点是实际应用程序现在会抛出此异常,并且不会通过 catch 块处理它来优雅地失败。

  1. 以某种方式抑制测试的异常记录。但这可能会导致在测试执行期间隐藏实际错误的日志。

这个question 有点相关,但没有完全回答我的问题。 我可以将所有测试堆栈跟踪重定向到像this 这样的文件,但我不想在测试执行期间重定向实际异常。 告诉特定测试不打印堆栈跟踪是理想的。

【问题讨论】:

  • this 线程的这个答案只接受这些日志。但我与许多可能会感到困惑并认为这些是实际例外的同事一起工作。
  • 使用记录器,并将记录器配置为不作为测试的一部分打印。不相关,但考虑将返回更改为 Optional<ObjectTransferData>
  • 我刚刚通读了 Robert C. Martin 的 Clean Code 一书,在关于错误处理的章节中发现了这条建议:如果出现问题,不要编写返回 null 的方法。而是抛出异常。所以我会改变我的函数来抛出异常。

标签: java unit-testing junit try-catch stack-trace


【解决方案1】:

您需要决定是要更改应用程序行为(并按照您的建议报告异常)还是保留该行为并返回 null。

但是还有第三种选择,尤其是在您进行单元测试之后: 将方法的功能分为两部分:

  1. 解析JSON并抛出异常的部分
  2. 捕获异常的包装函数,将其打印到标准输出并返回 null

您的单元测试现在可以测试 1) 而应用程序使用 2)。

如果您也不喜欢这样,您可以 - 在您的单元测试中 - 在调用抛出异常的东西之前将 stdout 重定向到一些临时 ByteArrayStream 中,然后不仅检查是否返回 null,而且检查字节数组是否接收到正确的数据.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    相关资源
    最近更新 更多