如何使用 MockIntegrationContext 测试消息驱动通道适配器

How to test message-driven-channel-adapter with MockIntegrationContext

我正在尝试测试 Spring 集成流程,该流程从配置为以下内容的消息驱动通道适配器开始:

<int-jms:message-driven-channel-adapter id="myAdapter" ... />

我的测试是这样的:

@SpringJUnitConfig(locations = {"my-app-context.xml"})
@SpringIntegrationTest(noAutoStartup = {"myAdapter"})
public class MyIntegrationFlowTest {

  @Autowired
  private MockIntegrationContext mockIntegrationContext;

  @Test
  public void myTest() {
    ...
    MessageSource<String> messageSource = () -> new GenericMessage<>("foo");
    mockIntegrationContext.substituteMessageSourceFor("myAdapter", messageSource);
    ...
  }
}

但是我收到以下错误:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'myAdapter' is expected to be of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' but was actually of type 'org.springframework.integration.jms.JmsMessageDrivenEndpoint'

如何使用 MockIntegrationContext 或其他方法为通道适配器指定备用源以进行测试?

消息驱动程序通道适配器实际上不是源轮询通道适配器。所以,substituteMessageSourceFor() 确实不能用于那种类型的组件,它本质上是一个 MessageProducerSupport 实现,而不是 SourcePollingChannelAdapter 用于 MessageSource.

存在差异是因为并非所有协议都提供类似侦听器的挂钩来生成一些要订阅的自我管理任务。很好的例子是 JDBC,它只是被动系统等待请求。因此,必须使用具有 JdbcPollingChannelAdapter(即 MessageSource)实现的轮询通道适配器以事件驱动的方式与 DB 交互。

其他系统(如您的 JMS)提供了一些侦听器(或消费者)API,我们可以生成一个 while 任务(参见 MessageListenerContainer 中的 spring-jms) 并让它 MessageProducerSupport 向频道发送消息。

因此在选择测试策略之前,您需要自己区分与什么类型的组件交互。

由于在消息驱动程序通道适配器的情况下没有额外的层,而是一些特定的、自我管理的 MessageProducerSupport impl,我们不仅提供了一个特定的模拟 API,甚至不需要知道任何其他信息,只需要了解标准单元测试功能和此端点在配置中生成的消息通道。

因此,适合您的解决方案如下:

  1. @SpringIntegrationTest(noAutoStartup = {"myAdapter"}) - 您的代码完全正确:我们确实必须停止真正的通道适配器,以免污染我们的测试环境。

  2. 您只需要在测试中注入 class 一个 id="myAdapter" 正在生成的 MessageChannel。在您的测试代码中,您只需构建一个 Message 并将其发送到此频道。根本不需要担心 MockIntegrationContext