无法对@KafkaListener带注释的方法进行单元测试

时间:2018-05-07 12:29:08

标签: spring unit-testing apache-kafka spring-kafka

我试图在Spring中对kafka消费者类进行单元测试。我想知道如果向它发送了一个kafka消息的主题,则正确调用了listener方法。我的消费者类注释如下:

@KafkaListener(topics = "${kafka.topics.myTopic}")
public void myKafkaMessageEvent(final String message) { ...

如果我@Autowire一个消费者,当我发送一个kafka消息时,正确调用了listener方法,但我不能断言该方法被调用,因为该类不是模拟的。

如果我模仿消费者,当我发送kafka消息时,根本不会调用监听器方法。我可以直接调用该方法,并断言它是有效的,但这并不是我想做的,也就是检查当我向其发送kafka消息时是否调用该方法。

现在我已经在消费者中设置了一个计数器,并在每次调用监听器方法时递增它,然后检查它的值是否已经改变。为测试做一个变量对我来说似乎是一个可怕的解决方案。

是否有办法让被模拟的消费者也收到kafka消息?或者其他一些断言非模拟消费者监听器方法被调用的方法?

1 个答案:

答案 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");