如何测试是否使用@KafkaListener的方法被调用

时间:2019-05-30 22:40:12

标签: java apache-kafka spring-kafka

我真的很想编写一个测试来检查将消息发送到其指定主题时是否正确调用了我的Kafka Consumer。

我的消费者:

@Service
@Slf4j
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class ProcessingConsumer {

  private AppService appService;

  @KafkaListener(
      topics = "${topic}",
      containerFactory = "processingConsumerContainerFactory")
  public void listen(ConsumerRecord<Key, Value> message, Acknowledgment ack) {
    try {
      appService.processMessage(message);
      ack.acknowledge();
    } catch (Throwable t) {
      log.error("error while processing message!", t);
    }
  }
}

我的消费者配置:

@EnableKafka
@Configuration
public class ProcessingCosumerConfig {

  @Value("${spring.kafka.schema-registry-url}")
  private String schemaRegistryUrl;

  private KafkaProperties props;

  public ProcessingCosumerConfig(KafkaProperties kafkaProperties) {
    this.props = kafkaProperties;
  }

  public Map<String, Object> deserializerConfigs() {
    Map<String, Object> props = new HashMap<>();
    props.put(KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG, true);
    props.put(KafkaAvroDeserializerConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl);

    return props;
  }

  private KafkaAvroDeserializer getKafkaAvroDeserializer(Boolean isKey) {
    KafkaAvroDeserializer kafkaAvroDeserializer = new KafkaAvroDeserializer();
    kafkaAvroDeserializer.configure(deserializerConfigs(), isKey);
    return kafkaAvroDeserializer;
  }

  private DefaultKafkaConsumerFactory consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(
        props.buildConsumerProperties(),
        getKafkaAvroDeserializer(true),
        getKafkaAvroDeserializer(false));
  }

  @Bean(name = "processingConsumerContainerFactory")
  public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<Key, Value>>
      kafkaListenerContainerFactory() {

    ConcurrentKafkaListenerContainerFactory<Key, Value>
        factory = new ConcurrentKafkaListenerContainerFactory<>();

    factory.setConsumerFactory(consumerFactory());
    factory.getContainerProperties().setAckOnError(false);
    factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
    factory.setErrorHandler(new SeekToCurrentErrorHandler());
    return factory;
  }
}

最后,我的(想)测试:

@DirtiesContext
public class ProcessingConsumerTest extends BaseIntegrationTest{

  @Autowired private ProcessingProducerFixture processingProducer;
  @Autowired private ProcessingConsumer processingConsumer;
  @org.springframework.beans.factory.annotation.Value("${topic}")
  String topic;

  @Test
  public void consumer_shouldConsumeMessages_whenMessagesAreSent() throws Exception{
    Thread.sleep(1000);
    ProducerRecord<Key, Value> message = new ProducerRecord<>(topic, new Key("b"), new Value("a", "b", "c", "d"));
    processingProducer.send(message);
  }
}

到目前为止,这就是我的全部。 我尝试过检查这种方法是否通过调试手动到达消费者,甚至只是将简单的打印内容放到那里,但是执行似乎并没有到达那里。另外,如果我的测试可以正确地调用它,那么我不知道该怎么做才能在实际测试中对其进行断言。

1 个答案:

答案 0 :(得分:0)

将模拟的AppService注入侦听器,并验证其processMessage()已被调用。