Java 带有slif4j日志的try catch块的mockito测试出现问题
我正在为一个try-catch块编写测试,但我对如何测试catch块感到非常困惑…尤其是它使用slf4j来记录错误 addText是来自同一类的另一个方法Java 带有slif4j日志的try catch块的mockito测试出现问题,java,unit-testing,spring-boot,testing,mockito,Java,Unit Testing,Spring Boot,Testing,Mockito,我正在为一个try-catch块编写测试,但我对如何测试catch块感到非常困惑…尤其是它使用slf4j来记录错误 addText是来自同一类的另一个方法 public class TextQueue { public void addTextToQueue(final Text text) { try { if (text != null) { addText(text);
public class TextQueue {
public void addTextToQueue(final Text text) {
try {
if (text != null) {
addText(text);
}
} catch (final JsonProcessingException e) {
LOGGER.error("Error adding text to the queue : {}", e);
}
}
}
这是我的测试用例
@RunWith(MockitoJUnitRunner.class)
public class TextQueueTest {
private org.slf4j.Logger LOGGER = LoggerFactory.getLogger(TextQueueTest.class);
private static final String MY_TEXT = "src/text.json";
private Text text;
private final ObjectMapper mapper = new JacksonConfig().dateAsStringObjectMapper();
@Mock
private TextQueue textQueue;
@Before
public void setUp() throws IOException {
text = mapper.readValue(new File(TextQueueTest.MY_TEXT), Text.class);
}
@Test
public void addTextToQueue() {
try{
textQueue = spy(textQueue);
textQueue.addTextToQueue(text);
}catch(final Exception e){
LOOGER.error("add text to queue threw an error" + e);
}
}
有人能帮我解决这个问题吗?首先,你真的应该读一本关于Mockito的很好的教程,比如来自美国的那本。你看,你只是简单地把很多非感官的东西放在一起 比如:
@Mock
private TextQueue textQueue;
拥有
textQueue = spy(textQueue);
在您的测试用例中。你应该非常清楚这一点。间谍是在测试类的真实实例上构建的。创造一个间谍,在一个模拟间谍,如说:这是没有意义的
然后:
}catch(final Exception e){
Logger.error("add text to queue threw an error" + e);
再一次,非感官的。单元测试的整体思想是,当出现问题时,单元测试会失败。当您的生产代码抛出意外的异常时,您不会记录它们,最终只会让它们在测试用例中失败
回答实际问题:生产代码似乎正在使用特定的“常量”记录器实例。鉴于这种设计,检查生产代码的唯一方法是:
- 使该记录器成为模拟对象
- 以某种方式将其注入到生产代码类的一个实例
测试中
- 触发该方法在
测试下进行测试(并以某种方式强制该方法引发异常)
- 验证模拟记录器是否看到了对
error()的预期调用
addTextToQueue()
您需要一种方法来调用“real”addTextToQueue()
实现,但是对内addTser()
的调用需要转到模拟(以便您可以控制该调用的功能)
但如前所述:从真正研究Mockito的工作原理开始,而不是将一些“尝试和错误”方法中毫无意义的东西放在一起。使用模拟进行正确的单元测试是复杂的,您无法通过“试错法”了解这一点。请注意:您的更新增加了混乱。现在您的测试类将不再编译,并且提示:在测试类中声明记录器实例对您的生产代码没有任何影响。从这个角度来看,如果可能的话,你可能应该重新审视并加强你的问题。或者让我知道我的答案中缺少了什么/如果。所以我不应该在测试中包括LOGGER,要用原始方法测试catch块,最好的方法是触发异常,然后验证异常,对吗@这取决于你想做什么。如果您只需检查:addTextToQueue()就可以捕获任何异常,那么不抛出异常的测试就足够了。但是,如果您想确保将某些消息写入记录器,则需要对其进行控制。再次强调:在测试用例中有一个LOGGER实例对您的产品代码没有任何作用。感谢您的建议,如果异常通过,我将尝试找到检查日志的方法。我感谢您的快速恢复!如前所述:关键是获得对记录器对象的控制。您可能想了解依赖项注入。真正的问题是:记录器实例如何进入您的生产代码?当你明白了这一点,你可以看看你的选择。这可能是你可以推一个模拟的记录器,如果这是不可能的,是的,看看真实记录器的“输出”就可以了。(但我建议避免这种情况,您希望将单元测试与任何“真实”的东西(如文件系统中的文件)隔离开来)