Java 使用throw发送KafkaTemplate.send的Mockito抛出异常
我正在测试以下函数Java 使用throw发送KafkaTemplate.send的Mockito抛出异常,java,spring-boot,junit,mockito,Java,Spring Boot,Junit,Mockito,我正在测试以下函数 公共布尔produceNumberOfPeople(NumberOfPeopleInPlacedToNumberOfPeopleInPlacedTo){ 最终生产记录=新生产记录( 卡夫卡诺图。按地点、主题划分的人数, numberOfPeopleInPlaceDTO.getId(), numberOfPeopleInPlaceDTO.getNumberOfPeople()); 试一试{ kafkaTemplate.send(record).get(2,TimeUnit.SE
公共布尔produceNumberOfPeople(NumberOfPeopleInPlacedToNumberOfPeopleInPlacedTo){
最终生产记录=新生产记录(
卡夫卡诺图。按地点、主题划分的人数,
numberOfPeopleInPlaceDTO.getId(),
numberOfPeopleInPlaceDTO.getNumberOfPeople());
试一试{
kafkaTemplate.send(record).get(2,TimeUnit.SECONDS);
返回true;
}
捕获(ExecutionException | TimeoutException | InterruptedException e){
返回false;
}
}
下面是测试代码
@测试
public void produceNumberOfPeopleTest()引发InterruptedException、ExecutionException、TimeoutException{
NumberOfPeopleInPlaceDTO NumberOfPeopleInPlaceDTO=NumberOfPeopleInPlaceDTO.builder()
.id(1)
.人数(10)
.build();
Mockito.when(kafkaTemplate.send(Mockito.any(ProducerRecord.class)))
.然后返回(可列出的未来);
Mockito.when(listenableFuture.get(2,TimeUnit.SECONDS))
.thenthow(TimeoutException.class);
Assert.assertFalse(placeService.produceNumberOfPeople(numberOfPeopleInPlaceDTO));
}
我定义了以下变量
@Autowired
私募服务;
@蚕豆
私人配售储存库;
@蚕豆
私人卡夫卡模板卡夫卡模板;
@蚕豆
私人可上市未来可上市未来;
问题是kafkaTemplate.send(record).get(2,TimeUnit.SECONDS)
不会引发异常。所以测试总是失败
请告知我缺少的任何内容。我建议创建失败的
ListenableFuture
对象,而不是Mock
SettableListenableFuture<SendResult<String, Object>> future = new SettableListenableFuture<>();
future.setException(new RuntimeException())
因此,当调用该方法时,它抛出ExecutionException
如果已通过set(Object)设置该值,则该方法返回该值;如果已通过setException(Throwable)设置异常,则抛出ExecutionException;如果已取消未来,则抛出CancellationException
问题是
PlaceService
没有使用KafkaTemplate
的模拟实例。因此,我手动将mock实例传递给PlaceService
的构造函数。现在测试通过了。下面是新的测试代码
@测试
public void produceNumberOfPeopleTest()引发InterruptedException、ExecutionException、TimeoutException{
NumberOfPeopleInPlaceDTO NumberOfPeopleInPlaceDTO=NumberOfPeopleInPlaceDTO.builder()
.id(1)
.人数(10)
.build();
PlaceService testPlaceService=new-PlaceServiceImpl(null,kafkaTemplate);
SettableListenableFuture=新的SettableListenableFuture();
setException(新的RuntimeException());
Mockito.when(kafkaTemplate.send(Mockito.any(ProducerRecord.class)),然后return(future);
Assert.assertFalse(testPlaceService.produceNumberOfPeople(numberOfPeopleInPlaceDTO));
}
我很高兴您通过将实例传递给构造函数来解决问题。然而,我将使用另一种方法,而不是创建适当的构造函数,并在测试方法本身中实例化
placeService
作为最佳实践,建议使用特定的setXXX方法来传递实例,例如在您的案例中,在PlaceService类中,您应该有如下内容:public void setListenableFuture(ListenableFuture listenableFuture) {
this.listenableFuture = listenableFuture;
}
public void setKafkaTemplate(KafkaTemplate<Integer, Integer> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
通过这种方式,您可以将Mock对象和placeService
保留为测试类的成员,这样JUnit和Spring Runner就有责任实例化这些对象并将它们注入placeService
,然后您就可以定制将要编写的每个测试方法的Mock行为,根据您的需要。根据我的经验,我发现这很有帮助,因为涉及的每个对象都有其适当的工作。即使在测试实现和可维护性方面,您也不必在每个测试方法中重复相同的代码。例如,考虑一下如果在某一点上您必须更改该构造函数会发生什么情况,在这种情况下,您也必须更改使用它的所有方法。你不觉得吗?你是否确保“placeService”使用了正确的“listenableFuture”和“kafkaTemplate”模拟实例?你把那些例子传给它了吗?否则,您正在模拟的方法实际上永远不会产生预期的结果,因为调用是在不同的实例上进行的。@Marctizano您的建议帮助很大。谢谢
public void setListenableFuture(ListenableFuture listenableFuture) {
this.listenableFuture = listenableFuture;
}
public void setKafkaTemplate(KafkaTemplate<Integer, Integer> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
@Before
public void setUp() throws Exception {
placeService.setListenableFuture(listenableFuture);
placeService.setKafkaTemplate(kafkaTemplate);
}