需要帮助UnitTest | Kafka自定义ConcurrentKafkaListenerContainerFactory与自定义记录FilterStrategy

时间:2020-08-04 01:55:45

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

尝试对具有自定义RecordFilterStrategy的ConcurrentKafkaListenerContainerFactory进行单元测试,但是无法找到测试过滤器策略的最佳方法。

  class ConsumerConfiguration {

  @Bean
  public ConcurrentKafkaListenerContainerFactory<String, Message> messageListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, Message> factory =
        new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    factory.setRecordFilterStrategy(consumerRecord -> consumerRecord.value().getType().contains("MYFILTER"));
    return factory;
  }

}

单元测试

  @Mock
  KafkaProperties kafkaProperties;
  ConsumerConfiguration configuration;
  @Test
  void testMessageListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, Message> actual =
        configuration.messageListenerContainerFactory();
    assertEquals(kafkaProperties.buildConsumerProperties(),
        actual.getContainerProperties().getKafkaConsumerProperties());
  }

尽管此代码适合于单元测试,但是不提供Custom RecordFilterStrategy的代码覆盖,即lambda函数,因此,如果有人已经对Kafka Listener Container Factory进行了单元测试/代码覆盖,那么最好的帮助是什么?进行处理。

1 个答案:

答案 0 :(得分:0)

对于出厂配置的纯单元测试,其中的过滤器是

record -> record.value().contains("foo")

您可以执行以下操作...

@SpringBootTest
class So63239177ApplicationTests {

    @Autowired
    ConcurrentKafkaListenerContainerFactory<String, String> factory;

    private int called;

    @Test
    void testFilter() throws Exception {
        MethodKafkaListenerEndpoint<String, String> endpoint = new MethodKafkaListenerEndpoint<>();
        endpoint.setBean(this);
        endpoint.setMethod(getClass().getDeclaredMethod("listen", ConsumerRecord.class));
        endpoint.setMessageHandlerMethodFactory(new DefaultMessageHandlerMethodFactory());
        endpoint.setTopics("foo");
        ConcurrentMessageListenerContainer<String, String> container = factory.createListenerContainer(endpoint);
        @SuppressWarnings("unchecked")
        MessageListener<String, String> messageListener =
                (MessageListener<String, String>) container.getContainerProperties().getMessageListener();
        messageListener.onMessage(new ConsumerRecord<>("foo", 0, 0L, null, "foo"));
        assertThat(this.called).isEqualTo(0);
        messageListener.onMessage(new ConsumerRecord<>("foo", 0, 0L, null, "bar"));
        assertThat(this.called).isEqualTo(1);
    }

    public void listen(ConsumerRecord<String, String> in) {
        this.called++;
    }

}

编辑

这是一种稍微简单(甚至更干净)的方式...

@SpringBootTest
class So632391771ApplicationTests {

    @Autowired
    KafkaListenerAnnotationBeanPostProcessor<?, ?> bpp;

    @Autowired
    KafkaListenerEndpointRegistry registry;

    @Test
    void testFilter() throws Exception {
        TestListener listener = new TestListener();
        this.bpp.postProcessAfterInitialization(listener, "test");
        ContainerProperties containerProperties = registry.getListenerContainer("test")
                .getContainerProperties();
        assertThat(containerProperties.getGroupId()).isEqualTo("test");
        @SuppressWarnings("unchecked")
        MessageListener<String, String> messageListener =
                    (MessageListener<String, String>) containerProperties.getMessageListener();
        messageListener.onMessage(new ConsumerRecord<>("foo", 0, 0L, null, "foo"));
        assertThat(listener.called).isEqualTo(0);
        messageListener.onMessage(new ConsumerRecord<>("foo", 0, 0L, null, "bar"));
        assertThat(listener.called).isEqualTo(1);
    }

}

class TestListener { // NOTE: Not a @Bean

    int called;

    @KafkaListener(id = "test", topics = "foo", autoStartup = "false")
    public void listen(String in) {
        this.called++;
    }

}
相关问题