Java(JUnit4.xx)如何使用模拟工具使用void方法强制调用try块中的异常?
下面是我的代码片段。我想使用WakeupException强制调用catch块Java(JUnit4.xx)如何使用模拟工具使用void方法强制调用try块中的异常?,java,unit-testing,junit,mockito,junit4,Java,Unit Testing,Junit,Mockito,Junit4,下面是我的代码片段。我想使用WakeupException强制调用catch块 public void run() { try { try { while (true) { LOGGER.logp(Level.INFO, CLASS_NAME, "run()", "Attempting to Poll"); ConsumerRecords<String, String> records = consu
public void run() {
try {
try {
while (true) {
LOGGER.logp(Level.INFO, CLASS_NAME, "run()", "Attempting to Poll");
ConsumerRecords<String, String> records = consumer.poll(10000);
if (records.count() == 0) {
LOGGER.logp(Level.INFO, CLASS_NAME, "run()", "No Response. Invalid Topic");
break;
}
else if(records.count()>0) {
LOGGER.logp(Level.INFO, CLASS_NAME, "run()", "Response Received");
}
}
}
} catch (WakeupException e) {
consumer.close();
}
}
我只想调用WakeupException,以便获得代码块的行覆盖率。我会怎么做。顺便说一下,这是一种无效的方法。我也愿意接受有关PowerMock的建议。看过代码后,我很确定我们要模拟的调用是
consumer.poll(…)
。我不是使用卡夫卡的专家,所以从这里开始,一切都要小心。考虑到consumer
是被测类的一个属性,应该可以将模拟实例注入被测类,并抛出我们需要的WakeupException
。我们创建一个使用者的(n个附加)模拟,并模拟其轮询(…)
-方法,以在调用时抛出所需的唤醒异常
,而不是(或附加到-您的决定)被测类。我们没有模拟对consumerThread3.run()
的调用,而是模拟对consumer.poll(…)
的调用
关于你的问题的评论:“我只想调用唤醒异常
,这样我就可以得到行覆盖率”——这永远不应该成为编写测试的理由。测试应该测试行为。如果没有要测试的行为(这种情况很少),则不要编写测试
OP编辑了问题并添加了一些附加信息。我很有信心,这篇文章的第一段应该回答这个问题。其他段落是在OP在try
-块中添加相关代码之前编写的。它们是在更抽象的层次上写的。感兴趣的读者可以阅读,但这不是理解答案的必要条件
お楽しみください! - 请欣赏
我们想验证catch
-块的行为。在生产代码中,try
-块中的某些内容将抛出相应的异常
,从而触发catch
-块。因此,为了测试catch
-块,我们应该模拟try
-块中的某个内容来抛出所述的异常
如果在块内模拟调用似乎是不可能的,那可能是因为代码不是由测试驱动开发的。你看,这种方法的一个好处是,你本质上生成了可测试的代码。如果我们被不稳定/难以测试的代码所困扰,我们有两个(或三个)选项:
- 保持原样,不要测试它。如果没有需要测试的行为,这可能是一个有效的答案
- 重写代码,使其可测试。根据项目的结构,这可能需要5分钟到2周或更长时间。不知道代码库很难说
- 使用非常规工具。正常的模拟框架(如)有一定的限制,例如。其他工具,如,旨在消除这些限制。但请注意:PowerMock是在字节码级别运行的。这意味着
- 我们不一定要测试生产中使用的字节码
- 这可能与其他工具(例如)一起拧紧
这些工具应该是你的最后手段,而且使用很少
“我只想调用WakeupException,以便获得该代码块的行覆盖率。”-错误的方法。不要为了测试或覆盖而测试。测试以验证行为。--你嘲笑错误的事情。模拟try
-块中的调用,该调用实际上可能引发WakeupException
。是否尝试测试模拟?您不应该模仿您试图测试的方法。您是否可以添加实际上需要您添加try捕获的代码?这也是为了正确地测试它而必须模仿的东西。您可能应该研究这种情况下的依赖项注入。@sandepnamburi可能是消费者需要try-catch。如果您将它设置在某个地方,您可以尝试将它从单元测试注入到类中。通常的代码气味会是,如果你的设计是不可测试的,你可以考虑一种TDD方法来避免未来:“代码>消费者<代码>如何设置在你的代码> KAFKACONSOMER测试< /代码>对象中?这就是你想要模拟的对象,你需要某种方法来注入它。@Turing85非常感谢你,我找到了它。我模仿了消费者调查,结果成功了。谢谢大家的帮助!
@Test(expected = WakeupException.class)
public void failRun() throws WakeupException, IOException {
KafkaConsumerForTests consumerThread3;
consumerThread3 = Mockito.mock(KafkaConsumerForTests.class);
doThrow(new WakeupException()).when(consumerThread3).run();
//Mockito.when(consumerThread2.run()).thenThrow(new WakeupException());
consumerThread3.run();
}