【问题标题】:issue with mockito test for try catch block with slif4j Log带有 slif4j 日志的 try catch 块的模拟测试问题
【发布时间】:2019-01-16 11:38:39
【问题描述】:

我正在为 try catch 块编写测试,但我对如何测试 catch 块感到很困惑……尤其是它使用 slf4j 来记录错误。

这里的addText 是同一个类的另一个方法。

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);
    }
}

谁能帮我解决这个问题?

【问题讨论】:

  • 请注意:您的更新增加了混乱。现在您的测试类将不再编译,并提示:在测试类中声明一个 LOGGER 实例对您的生产代码没有任何影响。从这个角度来看,如果可能的话,您可能应该重新访问minimal reproducible example 并相应地增强您的问题。或者让我知道我的答案中缺少什么/如果。
  • 所以我不应该在测试中包含LOGGER,在原始方法中测试catch块,最好的方法是触发异常然后验证异常,对吗? @鬼猫
  • 这取决于你想做什么。如果您只是检查“好”: addTextToQueue() 确实捕获了任何异常,那么不引发异常的测试就足够了。但是,如果您想确保将某些消息写入记录器,那么您需要获得对它的控制权。再说一遍:在您的测试用例中放置一个 LOGGER 实例不会在您的生产代码中做任何事情。
  • 感谢您的建议,如果异常抛出,我会尝试寻找检查日志的方法
  • 感谢您的快速回归!如前所述:关键是获得对记录器对象的控制权。您可能想阅读有关依赖注入的信息。真正的问题是:该 LOGGER 实例如何进入您的生产代码?当你明白这一点时,你可以看看你的选择。可能是你可以推入一个模拟的记录器,如果那不可能,是的,查看真实记录器的“输出”可以做到。 (但我建议避免这种情况,您希望将单元测试与任何“真实”事物(例如文件系统中的文件)隔离开来)

标签: java unit-testing spring-boot testing mockito


【解决方案1】:

首先,你真的应该阅读一篇关于 Mockito 的好教程,比如来自 vogella 的教程。你看,你只是把很多无意义的东西放在一起。

喜欢:

@Mock
private TextQueue textQueue;

然后拥有

textQueue = spy(textQueue);

在您的测试用例中。你应该很清楚这一点。间谍建立在您的测试类的真实实例之上。如前所述,创建一个监视模拟的间谍:这没有任何意义。

然后:

}catch(final Exception e){
    Logger.error("add text to queue threw an error" + e);

再一次,毫无意义。单元测试的整体理念是当出现问题时它们失败。当您的生产代码抛出意外异常时,您不会记录它们,您只是让它们最终使您的测试用例失败。

回答实际问题:看起来您的生产代码正在使用特定的“常量”记录器实例。鉴于这种设计,检查生产代码的唯一方法是:

  • 将 LOGGER 设为模拟对象
  • 以某种方式将其注入生产代码类的实例 underTest
  • 触发该方法在underTest 上进行测试(并以某种方式强制该方法抛出异常)
  • 验证模拟的 LOGGER 看到了对 error() 的预期调用

我们无法提供更好的建议,因为您的代码输入不足,我们并不真正知道您的生产类在做什么(例如:我们不知道 LOGGER 是什么,以及它的来历来自。如果它碰巧是一个静态变量,那么很可能,你不能用 Mockito 来“控制”它)。

无论如何,您可能确实需要 spy 概念。为了测试addTextToQueue(),您需要一种方法来调用“真实的”addTextToQueue() 实现,但在内部对addTser() 的调用需要进行模拟(以便您可以控制该调用的作用)。

但如前所述:从真正开始研究 Mockito 的工作原理,而不是将在某些“试错”方法中没有意义的东西放在一起。使用模拟进行正确的单元测试很复杂,您无法通过“反复试验”来学习。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多