我试图在Spring中对kafka消费者类进行单元测试。我想知道如果向它发送了一个kafka消息的主题,则正确调用了listener方法。我的消费者类注释如下:
@KafkaListener(topics = "${kafka.topics.myTopic}")
public void myKafkaMessageEvent(final String message) { ...
如果我@Autowire一个消费者,当我发送一个kafka消息时,正确调用了listener方法,但我不能断言该方法被调用,因为该类不是模拟的。
如果我模仿消费者,当我发送kafka消息时,根本不会调用监听器方法。我可以直接调用该方法,并断言它是有效的,但这并不是我想做的,也就是检查当我向其发送kafka消息时是否调用该方法。
现在我已经在消费者中设置了一个计数器,并在每次调用监听器方法时递增它,然后检查它的值是否已经改变。为测试做一个变量对我来说似乎是一个可怕的解决方案。
是否有办法让被模拟的消费者也收到kafka消息?或者其他一些断言非模拟消费者监听器方法被调用的方法?
答案 0 :(得分:1)
听起来你要求的东西类似于我们在Spring AMQP测试框架中所拥有的东西:https://docs.spring.io/spring-amqp/docs/2.0.3.RELEASE/reference/html/_reference.html#test-harness
所以,如果你不擅长使用额外的变量,你可以借用solution并实现自己的"线束"。
我认为这应该是框架的一个很好的补充,所以,请提出一个适当的issue,我们可以一起为公众带来这样的工具。
<强>更新强>
因此,根据Spring AMQP基础,我在测试配置中做到了这一点:
public static class KafkaListenerTestHarness extends KafkaListenerAnnotationBeanPostProcessor {
private final Map<String, Object> listeners = new HashMap<>();
@Override
protected void processListener(MethodKafkaListenerEndpoint endpoint, KafkaListener kafkaListener,
Object bean, Object adminTarget, String beanName) {
bean = Mockito.spy(bean);
this.listeners.put(kafkaListener.id(), bean);
super.processListener(endpoint, kafkaListener, bean, adminTarget, beanName);
}
@SuppressWarnings("unchecked")
public <T> T getSpy(String id) {
return (T) this.listeners.get(id);
}
}
...
@SuppressWarnings("rawtypes")
@Bean(name = KafkaListenerConfigUtils.KAFKA_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static KafkaListenerTestHarness kafkaListenerAnnotationBeanPostProcessor() {
return new KafkaListenerTestHarness();
}
然后在目标测试用例中我使用它:
@Autowired
private KafkaListenerTestHarness harness;
...
Listener listener = this.harness.getSpy("foo");
verify(listener, times(2)).listen1("foo");