在测试 Spring Cloud Stream 函数时,Spring Cloud Contract outputMessage 通道 bean 不是 org.springframework.messaging.PollableChannel
On testing Spring Cloud Stream function, Spring Cloud Contract outputMessage channel bean is not a org.springframework.messaging.PollableChannel
我正在尝试创建一个 Spring 云合同来测试使用 Spring 云流时的消息。我在 pom.xml
中包含了依赖项
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<!--TEST-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<type>test-jar</type>
<scope>test</scope>
<classifier>test-binder</classifier>
</dependency>
并配置了合同插件
<!-- Contracts -->
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<baseClassForTests>com.example.streams.kafkastreamer.KafkaStreamerApplicationTests
</baseClassForTests>
</configuration>
</plugin>
然后我在本地 运行 一个简单的应用程序,以检查是否一切都按预期工作。但是,在 documentation 之后创建 Spring Cloud Contract 测试后,我收到以下错误,而 运行 生成的测试
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'uppercase-out-0' is expected to be of type 'org.springframework.messaging.PollableChannel' but was actually of type 'org.springframework.cloud.stream.messaging.DirectWithAttributesChannel'
我已经检查过创建的测试看起来像文档中的那个,对我来说有点像
@Test
public void validate_consume() throws Exception {
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"[\"MIAU\"]"
, headers()
.header("sample", "header")
);
// when:
contractVerifierMessaging.send(inputMessage, "uppercase-in-0");
// then:
ContractVerifierMessage response = contractVerifierMessaging.receive("uppercase-out-0");
assertThat(response).isNotNull();
// and:
assertThat(response.getHeader("contentType")).isNotNull();
assertThat(response.getHeader("contentType").toString()).isEqualTo("application/json");
// and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("['attributes']").field("['id']").isEqualTo("com.example.streams.kafkastreamer.KafkaStreamerApplication$$EnhancerBySpringCGLIB$$cf6cc14c2020-03-05T12:07:05.366");
assertThatJson(parsedJson).field("['attributes']").field("['source']").isEqualTo("file:///com/example/streams/kafkastreamer");
assertThatJson(parsedJson).field("['attributes']").field("['specversion']").isEqualTo("1.0");
assertThatJson(parsedJson).field("['attributes']").field("['type']").isEqualTo("My.test.event.type");
assertThatJson(parsedJson).field("['attributes']").field("['datacontenttype']").isEqualTo("application/json");
assertThatJson(parsedJson).field("['attributes']").field("['dataschema']").isNull();
assertThatJson(parsedJson).field("['attributes']").field("['subject']").isNull();
assertThatJson(parsedJson).field("['attributes']").field("['time']").isNull();
assertThatJson(parsedJson).field("['data']").field("['value']").isEqualTo("MIAU");
assertThatJson(parsedJson).field("['dataBase64']").isNull();
assertThatJson(parsedJson).field("['extensions']").field("['specversion']").isEqualTo("1.0");
assertThatJson(parsedJson).array("['extensionsFormats']").isEmpty();
}
在 Spring 云合同文档示例中,正在使用 jms 并且通道设置为 sentTo('jms:output')
。由于我使用的是 Spring Cloud Stream Binder,因此我根据我的活页夹的定义将频道名称设置为 sentTo('uppercase-out-0')
。这是我的应用程序属性
#stubrunner.integration.enabled: false To make sure is using Spring Cloud Stream
spring.cloud.stream.bindings.uppercase-in-0.destination=test
spring.cloud.stream.bindings.uppercase-in-0.group=testGroup
spring.cloud.stream.bindings.uppercase-out-0.destination=hood
spring.cloud.stream.bindings.consume-in-0.destination=hood
spring.cloud.stream.bindings.consume-out-0.destination=downtown
spring.cloud.function.definition=uppercase;consume
我的问题是,为什么通道 uppercase-out-0 没有实现所需的 PollableChannel?我想我误解了来自 Spring Cloud Stream 或 Spring Cloud Contract 的官方文档中的某些内容,但无法理解。
还有一些信息。我的猜测是自动配置正在配置 SpringIntegrationSubMessages
类型的 bean,但应该是 StreamStubMessages
。但是,我不知道这是怎么发生的,也不知道为什么会发生。我猜对了吗?
问题出在我的 parent 测试 class 配置中。在某些时候,我的 IDE 建议我添加一个组件扫描,因为没有为
找到一个 bean
@Autowired
private MessageVerifier verifier;
所以我添加了 @ComponentScan(basePackages={"org.springframework.cloud.contract.verifier.messaging"})
并最终初始化了一些 bean,这些 bean 使 ContractVerifierStreamAutoConfiguration
中的条件 bean 未被配置,但是 SpringIntegrationSubMessages
。发现在官方文档中查看没有包含 @ComponentScan
并且我清理了我的代码
我正在尝试创建一个 Spring 云合同来测试使用 Spring 云流时的消息。我在 pom.xml
中包含了依赖项<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<!--TEST-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<type>test-jar</type>
<scope>test</scope>
<classifier>test-binder</classifier>
</dependency>
并配置了合同插件
<!-- Contracts -->
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<baseClassForTests>com.example.streams.kafkastreamer.KafkaStreamerApplicationTests
</baseClassForTests>
</configuration>
</plugin>
然后我在本地 运行 一个简单的应用程序,以检查是否一切都按预期工作。但是,在 documentation 之后创建 Spring Cloud Contract 测试后,我收到以下错误,而 运行 生成的测试
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'uppercase-out-0' is expected to be of type 'org.springframework.messaging.PollableChannel' but was actually of type 'org.springframework.cloud.stream.messaging.DirectWithAttributesChannel'
我已经检查过创建的测试看起来像文档中的那个,对我来说有点像
@Test
public void validate_consume() throws Exception {
// given:
ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
"[\"MIAU\"]"
, headers()
.header("sample", "header")
);
// when:
contractVerifierMessaging.send(inputMessage, "uppercase-in-0");
// then:
ContractVerifierMessage response = contractVerifierMessaging.receive("uppercase-out-0");
assertThat(response).isNotNull();
// and:
assertThat(response.getHeader("contentType")).isNotNull();
assertThat(response.getHeader("contentType").toString()).isEqualTo("application/json");
// and:
DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("['attributes']").field("['id']").isEqualTo("com.example.streams.kafkastreamer.KafkaStreamerApplication$$EnhancerBySpringCGLIB$$cf6cc14c2020-03-05T12:07:05.366");
assertThatJson(parsedJson).field("['attributes']").field("['source']").isEqualTo("file:///com/example/streams/kafkastreamer");
assertThatJson(parsedJson).field("['attributes']").field("['specversion']").isEqualTo("1.0");
assertThatJson(parsedJson).field("['attributes']").field("['type']").isEqualTo("My.test.event.type");
assertThatJson(parsedJson).field("['attributes']").field("['datacontenttype']").isEqualTo("application/json");
assertThatJson(parsedJson).field("['attributes']").field("['dataschema']").isNull();
assertThatJson(parsedJson).field("['attributes']").field("['subject']").isNull();
assertThatJson(parsedJson).field("['attributes']").field("['time']").isNull();
assertThatJson(parsedJson).field("['data']").field("['value']").isEqualTo("MIAU");
assertThatJson(parsedJson).field("['dataBase64']").isNull();
assertThatJson(parsedJson).field("['extensions']").field("['specversion']").isEqualTo("1.0");
assertThatJson(parsedJson).array("['extensionsFormats']").isEmpty();
}
在 Spring 云合同文档示例中,正在使用 jms 并且通道设置为 sentTo('jms:output')
。由于我使用的是 Spring Cloud Stream Binder,因此我根据我的活页夹的定义将频道名称设置为 sentTo('uppercase-out-0')
。这是我的应用程序属性
#stubrunner.integration.enabled: false To make sure is using Spring Cloud Stream
spring.cloud.stream.bindings.uppercase-in-0.destination=test
spring.cloud.stream.bindings.uppercase-in-0.group=testGroup
spring.cloud.stream.bindings.uppercase-out-0.destination=hood
spring.cloud.stream.bindings.consume-in-0.destination=hood
spring.cloud.stream.bindings.consume-out-0.destination=downtown
spring.cloud.function.definition=uppercase;consume
我的问题是,为什么通道 uppercase-out-0 没有实现所需的 PollableChannel?我想我误解了来自 Spring Cloud Stream 或 Spring Cloud Contract 的官方文档中的某些内容,但无法理解。
还有一些信息。我的猜测是自动配置正在配置 SpringIntegrationSubMessages
类型的 bean,但应该是 StreamStubMessages
。但是,我不知道这是怎么发生的,也不知道为什么会发生。我猜对了吗?
问题出在我的 parent 测试 class 配置中。在某些时候,我的 IDE 建议我添加一个组件扫描,因为没有为
找到一个 bean@Autowired
private MessageVerifier verifier;
所以我添加了 @ComponentScan(basePackages={"org.springframework.cloud.contract.verifier.messaging"})
并最终初始化了一些 bean,这些 bean 使 ContractVerifierStreamAutoConfiguration
中的条件 bean 未被配置,但是 SpringIntegrationSubMessages
。发现在官方文档中查看没有包含 @ComponentScan
并且我清理了我的代码