使用测试容器 pubsub 模拟器的反序列化问题

Rla*_*que 5 java spring google-cloud-pubsub testcontainers

我在使用 Spring 应用程序进行集成测试时遇到问题。我正在使用 testcontainer 设置 pubsub 模拟器:

@Container
private static final PubSubEmulatorContainer pubsubEmulator =
    new PubSubEmulatorContainer(DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:317.0.0-emulators"));

@DynamicPropertySource
static void emulatorProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.cloud.gcp.pubsub.emulator-host", pubsubEmulator::getEmulatorEndpoint);
}

@Bean
CredentialsProvider googleCredentials() {
    return NoCredentialsProvider.create();
}
Run Code Online (Sandbox Code Playgroud)

我正在发布这样的消息:

publisherTemplate.publish("My_Topic", "{\"name\": \"test\"}", headers)
Run Code Online (Sandbox Code Playgroud)

这是我的 pubsub 和 jackson 的应用程序配置:

@Configuration
@RequiredArgsConstructor
public class PubSubConsumerConfiguration {

    private final ConsumerRepository consumerRepository;

    @Bean
     public PubSubMessageConverter pubSubMessageConverter(ObjectMapper objectMapper) {
        return new JacksonPubSubMessageConverter(objectMapper);
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        return mapper;
    }

    @Bean
    public MessageChannel inputMessageChannel() {
        return new PublishSubscribeChannel();
    }

    @Bean
    public PubSubInboundChannelAdapter inboundChannelAdapter(MessageChannel inputMessageChannel, PubSubTemplate pubSubTemplate) {
        PubSubInboundChannelAdapter adapter = new 
        PubSubInboundChannelAdapter(pubSubTemplate, "my_sub");
        adapter.setOutputChannel(messageChannel);
        adapter.setAckMode(AckMode.MANUAL);
        adapter.setPayloadType(Consumer.class);
        return adapter;
    }

    @ServiceActivator(inputChannel = "inputMessageChannel")
    public void messageReceiver(
        @Payload Consumer payload,
        @Header(GcpPubSubHeaders.ORIGINAL_MESSAGE) BasicAcknowledgeablePubsubMessage message
    ) {

        consumerRepository.save(payload);
        message.ack();
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在定义一个 bean 来将 jackson 设置为从 pubsub 反序列化消息有效负载的主要方式。在 GCP 上使用 pubsub 一切都运行良好,我在控制台中发送的有效负载已正确反序列化并保存到数据库中。但是,在我与 pubsub 的测试容器版本的集成测试中,我在反序列化期间收到此错误:

com.google.cloud.spring.pubsub.support.converter.PubSubMessageConversionException: 
JSON deserialization of an object of type com.mypackage.model.Consumer failed.; 
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot construct instance of `com.mypackage.model.Consumer` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"name": "test"}')
Run Code Online (Sandbox Code Playgroud)

是我的测试方法有问题吗?

编辑:按照@Ilya的要求,这里是 com.mypackage.model.Consumer 类的内容示例,我尝试过使用和不使用空构造函数等。:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Consumer  {

    private String name;
    private ZonedDateTime deletedOn;
    ...
}
Run Code Online (Sandbox Code Playgroud)

Rla*_*que 2

我实际上通过更深入地查看此文档找到了答案。该问题来自我在将消息发布到 pubsub 时指定有效负载的方式。

publisherTemplate.publish("My_Topic", ByteString.copyFromUtf8("{\"name\": \"test\"}"), headers)
Run Code Online (Sandbox Code Playgroud)