Spring boot 卡夫卡消费记录返回空值
尝试在spring引导应用程序中实现单元测试时,我无法检索Spring boot 卡夫卡消费记录返回空值,spring-boot,spring-kafka,Spring Boot,Spring Kafka,尝试在spring引导应用程序中实现单元测试时,我无法检索消费者记录,尽管使用自己的POJO的自定义序列化程序正在工作。我与kafka控制台使用者进行了检查,每次运行测试时都会生成一条新消息并显示在控制台上。 要获取记录而不是null,我必须做什么 @RunWith(SpringRunner.class) @SpringBootTest @DisplayName("Testing GlobalMessageTest") @DirtiesContext public class NumberPla
消费者记录
,尽管使用自己的POJO的自定义序列化程序正在工作。我与kafka控制台使用者进行了检查,每次运行测试时都会生成一条新消息并显示在控制台上。
要获取记录而不是null
,我必须做什么
@RunWith(SpringRunner.class)
@SpringBootTest
@DisplayName("Testing GlobalMessageTest")
@DirtiesContext
public class NumberPlateSenderTest {
private static Logger log = LogManager.getLogger(NumberPlateSenderTest.class);
@Autowired
KafkaeskAdapterApplication kafkaeskAdapterApplication;
@Autowired
private NumberPlateSender numberPlateSender;
private KafkaMessageListenerContainer<String, NumberPlate> container;
private BlockingQueue<ConsumerRecord<String, NumberPlate>> records;
private static final String SENDER_TOPIC = "numberplate_test_topic";
@ClassRule
public static KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, SENDER_TOPIC);
@Before
public void setUp() throws Exception {
// set up the Kafka consumer properties
Map<String, Object> consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka);
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, NumberPlateDeserializer.class);
// create a Kafka consumer factory
DefaultKafkaConsumerFactory<String, NumberPlate> consumerFactory =
new DefaultKafkaConsumerFactory<>(consumerProperties);
// set the topic that needs to be consumed
ContainerProperties containerProperties = new ContainerProperties(SENDER_TOPIC);
// create a Kafka MessageListenerContainer
container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties);
// create a thread safe queue to store the received message
records = new LinkedBlockingQueue<>();
// setup a Kafka message listener
container.setupMessageListener((MessageListener<String, NumberPlate>) record -> {
log.info("Message Listener received message='{}'", record.toString());
records.add(record);
});
// start the container and underlying message listener
container.start();
// wait until the container has the required number of assigned partitions
ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic());
}
@DisplayName("Should send a Message to a Producer and retrieve it")
@Test
public void TestProducer() throws InterruptedException {
//Test instance of Numberplate to send
NumberPlate localNumberplate = new NumberPlate();
byte[] bytes = "0x33".getBytes();
localNumberplate.setImageBlob(bytes);
localNumberplate.setNumberString("ABC123");
log.info(localNumberplate.toString());
//Send it
numberPlateSender.sendNumberPlateMessage(localNumberplate);
//Retrieve it
ConsumerRecord<String, NumberPlate> received = records.poll(3, TimeUnit.SECONDS);
log.info("Received the following content of ConsumerRecord: {}", received);
if (received == null) {
assert false;
} else {
NumberPlate retrNumberplate = received.value();
Assert.assertEquals(retrNumberplate, localNumberplate);
}
}
@After
public void tearDown() {
// stop the container
container.stop();
}
@RunWith(SpringRunner.class)
@春靴测试
@DisplayName(“测试GlobalMessageTest”)
@肮脏的环境
公共类编号PlateSenderTest{
私有静态记录器log=LogManager.getLogger(NumberPlateSenderTest.class);
@自动连线
卡夫卡式应用卡夫卡式应用;
@自动连线
私人号码PlateSender号码PlateSender;
卡夫卡专用集装箱;
私有阻塞队列记录;
私有静态最终字符串发送器\u TOPIC=“numberplate\u test\u TOPIC”;
@阶级规则
public static kafkamebedded embedded kafka=新的kafkamebedded(1,true,发送方\主题);
@以前
public void setUp()引发异常{
//设置卡夫卡消费者属性
Map consumerProperties=KafkaTestUtils.consumerProps(“发送方”,“假”,嵌入kafka);
consumerProperties.put(ConsumerConfig.KEY\u反序列化程序\u类\u配置,StringDeserializer.CLASS);
consumerProperties.put(ConsumerConfig.VALUE\u反序列化程序\u类\u配置,NumberPlateDeserializer.CLASS);
//创建卡夫卡消费品工厂
默认卡夫卡消费者工厂消费者工厂=
新的默认卡夫卡消费者工厂(消费者财产);
//设置需要使用的主题
ContainerProperties ContainerProperties=新的ContainerProperty(发送者主题);
//创建Kafka MessageListenerContainer
容器=新的KafkaMessageListenerContainer(consumerFactory、containerProperties);
//创建线程安全队列以存储收到的消息
记录=新建LinkedBlockingQueue();
//设置卡夫卡消息侦听器
container.setupMessageListener((MessageListener)记录->{
log.info(“消息侦听器接收到消息='{}',record.toString());
记录。添加(记录);
});
//启动容器和底层消息侦听器
container.start();
//等待容器具有所需数量的分配分区
ContainerTestUtils.waitForAssignment(容器,embeddedKafka.getPartitionsPerTopic());
}
@DisplayName(“应向制作人发送消息并检索它”)
@试验
public void TestProducer()引发InterruptedException{
//要发送的Numberplate的测试实例
NumberPlate localNumberplate=新NumberPlate();
byte[]bytes=“0x33”。getBytes();
localNumberplate.setImageBlob(字节);
localNumberplate.setNumberString(“ABC123”);
log.info(localNumberplate.toString());
//发送它
numberPlateSender.sendNumberPlateMessage(localNumberplate);
//找回它
接收到的ConsumerRecord=记录。轮询(3,时间单位。秒);
log.info(“收到了ConsumerRecord的以下内容:{}”,已收到);
如果(接收==null){
断言错误;
}否则{
NumberPlate retrNumberplate=received.value();
Assert.assertEquals(retrNumberplate、localNumberplate);
}
}
@之后
公共无效拆卸(){
//停止容器
container.stop();
}
}
完整的代码可以在我的网站上看到。
我阅读了大量不同的SO问题并在网上搜索,但找不到一种方法来说明我的代码有什么问题。其他用户也发布了类似的问题,但没有效果
在我的Craptop上运行的卡夫卡版本是kafka_2.11-1.0.1
springframework kafka客户端的版本为2.1.5。发布版您的问题是,您启动了针对嵌入式kafka的消费者,但将数据发送到了真实的消费者。我不知道你的目标是什么,但我让它针对嵌入式卡夫卡工作,如下所示:
@BeforeClass
public static void setup() {
System.setProperty("kafka.bootstrapAddress", embeddedKafka.getBrokersAsString());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NumberPlate that = (NumberPlate) o;
return Objects.equals(numberString, that.numberString) &&
Arrays.equals(imageBlob, that.imageBlob);
}
@Override
public int hashCode() {
int result = Objects.hash(numberString);
result = 31 * result + Arrays.hashCode(imageBlob);
return result;
}
我使用嵌入的kafka提供的代理地址覆盖生产者的kafka.bootstrapAddress
配置属性
在这种情况下,我失败了:
java.lang.AssertionError: expected: dev.semo.kafkaeskadapter.models.NumberPlate<NumberPlate{numberString='ABC123', imageBlob=[48, 120, 51, 51]}> but was: dev.semo.kafkaeskadapter.models.NumberPlate<NumberPlate{numberString='ABC123', imageBlob=[48, 120, 51, 51]}>
Expected :dev.semo.kafkaeskadapter.models.NumberPlate<NumberPlate{numberString='ABC123', imageBlob=[48, 120, 51, 51]}>
Actual :dev.semo.kafkaeskadapter.models.NumberPlate<NumberPlate{numberString='ABC123', imageBlob=[48, 120, 51, 51]}>
同时,您的NumberPlate
没有提供正确的equals()
实现。大概是这样的:
@BeforeClass
public static void setup() {
System.setProperty("kafka.bootstrapAddress", embeddedKafka.getBrokersAsString());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NumberPlate that = (NumberPlate) o;
return Objects.equals(numberString, that.numberString) &&
Arrays.equals(imageBlob, that.imageBlob);
}
@Override
public int hashCode() {
int result = Objects.hash(numberString);
result = 31 * result + Arrays.hashCode(imageBlob);
return result;
}
感谢您提供整个项目来播放和复制!使用“问答”游戏,我们将在这里花费太多时间:-)。感谢您的时间和建议。我会推动它,并感谢你的帮助。耶!