在 JUnit 中测试包含 try/catch 块的方法的最佳方法
Best way to test a method containing a try/catch block in JUnit
我有以下方法。该方法使用 Jackson ObjectMapper 转换 json 字符串的内容。如果 json 格式不正确,则会打印堆栈跟踪并将对象设置为空:
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()
打印到我的终端中,这在测试执行期间掩盖了实际的重要日志。测试执行的 reader 可能会造成混淆。
我想知道如何解决这个问题。我想到了这些想法:
- 删除 try/catch 并抛出异常。这将允许我像这样编写测试,而不是将堆栈跟踪记录到控制台中。
@Test
public void testExtractJacksonObjectsFromFile_malformedJson_expectException(){
String malformedJson = "{";
assertThrows(Exception.class, () ->
objectImportService.extractJacksonObjectsFromFile(malformedJson)
);
}
然而,缺点是实际应用程序现在会抛出此异常,并且不会通过 catch 块处理它来优雅地失败。
- 以某种方式抑制测试的异常记录。但这可能会导致在测试执行期间抑制实际错误的日志。
这个有点相关,但没有完全回答我的问题。
我可以将所有测试堆栈跟踪重定向到 this 之类的文件,但我不想在测试执行期间重定向实际异常。
告诉特定测试不打印堆栈跟踪将是理想的。
您需要决定是要更改应用程序行为(并按照您已经建议的那样报告异常)还是保持该行为,return 为 null。
但是还有第三种选择,特别是因为您正在进行单元测试:
将您的方法的功能分为两部分:
- 解析JSON并抛出异常的部分
- 一个捕获异常的包装函数,将其打印到标准输出并且 returns null
您的单元测试现在可以测试 1),而应用程序使用 2)。
如果你也不喜欢这样,你可以 - 在你的单元测试中 - 在调用异常抛出东西之前将 stdout 重定向到一些临时的 ByteArrayStream ,然后不仅检查 null 是否被 returned 而且如果字节数组接收到正确的数据。
我有以下方法。该方法使用 Jackson ObjectMapper 转换 json 字符串的内容。如果 json 格式不正确,则会打印堆栈跟踪并将对象设置为空:
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()
打印到我的终端中,这在测试执行期间掩盖了实际的重要日志。测试执行的 reader 可能会造成混淆。
我想知道如何解决这个问题。我想到了这些想法:
- 删除 try/catch 并抛出异常。这将允许我像这样编写测试,而不是将堆栈跟踪记录到控制台中。
@Test
public void testExtractJacksonObjectsFromFile_malformedJson_expectException(){
String malformedJson = "{";
assertThrows(Exception.class, () ->
objectImportService.extractJacksonObjectsFromFile(malformedJson)
);
}
然而,缺点是实际应用程序现在会抛出此异常,并且不会通过 catch 块处理它来优雅地失败。
- 以某种方式抑制测试的异常记录。但这可能会导致在测试执行期间抑制实际错误的日志。
这个
您需要决定是要更改应用程序行为(并按照您已经建议的那样报告异常)还是保持该行为,return 为 null。
但是还有第三种选择,特别是因为您正在进行单元测试: 将您的方法的功能分为两部分:
- 解析JSON并抛出异常的部分
- 一个捕获异常的包装函数,将其打印到标准输出并且 returns null
您的单元测试现在可以测试 1),而应用程序使用 2)。
如果你也不喜欢这样,你可以 - 在你的单元测试中 - 在调用异常抛出东西之前将 stdout 重定向到一些临时的 ByteArrayStream ,然后不仅检查 null 是否被 returned 而且如果字节数组接收到正确的数据。