如何使用模仿来为春季集成豆构建模拟
我在测试应用程序时遇到了一个问题,如果我想替换Imapidlechanneladapter,我不明白我需要做什么 用 spring文档
public class ImapConfiguration{
@Bean
ImapMailReceiver getReceiver() {
ImapMailReceiver receiver = new ImapMailReceiver(ImapConfig.getUri());
return receiver;
}
@Bean
ImapIdleChannelAdapter getAdapter(ImapMailReceiver receiver) {
ImapIdleChannelAdapter adapter = new InternalImapIdleChannelAdapter(receiver);
adapter.setAutoStartup(true);
return adapter;
}
@Bean
StandardIntegrationFlow getFlow(ImapIdleChannelAdapter adapter, GenericHandler handler) {
return IntegrationFlows.from(adapter)
.handle(handler)
.get();
}
}
Spring Integration Document 在模拟整合部分中说:“模拟整合工厂提供了一个API,可以为集成流的一部分构建春季集成豆的模拟(Messageource,MessageProducer,MessageHandler和MessageChannel)。您还可以在配置阶段使用目标模拟就像在执行验证和断言之前替换实际端点的目标测试方法中一样”。我在春季集成文档中没有使用MessageProducer找到任何示例,在GitHub上的Spring Integration样本存储库中没有找到任何示例。我编写了测试,以尝试
@SpringBootTest(classes = ImapConfiguration.class)
@Import({ReceiverTestConf.class})
@SpringIntegrationTest(noAutoStartup = "inboundChannelAdapter")
public class ImapMailReceiverTest {
@Captor
ArgumentCaptor<ReceivedMail> emailCaptor = ArgumentCaptor.forClass(ReceivedMail.class);
@MockBean
TestEmailHandler emailHandlerTestImpl;
@Autowired
TestImapReceiver imapReceiver;
@Autowired
MockIntegrationContext mockIntegrationContext;
@Test
@SneakyThrows
void receive() throws MessagingException {
Mockito.doNothing().when(emailHandlerTestImpl).handle(Mockito.any());
MessageSource<MimeMessage> message = () -> {
return new GenericMessage<>("testMessage");
};
this.mockIntegrationContext.substituteMessageSourceFor("imapIdleChannelAdapter", MockIntegration.mockMessageSource(message));
idleChannelAdapter.start();
await().atMost(1, TimeUnit.SECONDS).untilAsserted(() -> {
Mockito.verify(emailHandlerTestImpl, Mockito.times(1)).handle(emailCaptor.capture());
List<ReceivedMail> result = emailCaptor.getAllValues();
Assertions.assertEquals(1, result.size());
}
);
}
在进行测试时尝试替换Imapidlechanneladapter,我会得到例外。
Bean named 'imapIdleChannelAdapter' is expected to be of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' but was actually of type 'com.test.emailadapter.imap.InternalImapIdleChannelAdapter'
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'imapIdleChannelAdapter' is expected to be of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' but was actually of type 'com.test.emailadapter.imap.InternalImapIdleChannelAdapter'
at app//org.springframework.beans.factory.support.AbstractBeanFactory.adaptBeanInstance(AbstractBeanFactory.java:417)
at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:398)
at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:217)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:157)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:142)
I met a problem in test of my application,I dont understand what i need to do if i want to replace ImapIdleChannelAdapter as it is
written in the spring documentation
public class ImapConfiguration{
@Bean
ImapMailReceiver getReceiver() {
ImapMailReceiver receiver = new ImapMailReceiver(ImapConfig.getUri());
return receiver;
}
@Bean
ImapIdleChannelAdapter getAdapter(ImapMailReceiver receiver) {
ImapIdleChannelAdapter adapter = new InternalImapIdleChannelAdapter(receiver);
adapter.setAutoStartup(true);
return adapter;
}
@Bean
StandardIntegrationFlow getFlow(ImapIdleChannelAdapter adapter, GenericHandler handler) {
return IntegrationFlows.from(adapter)
.handle(handler)
.get();
}
}
In the spring integration documentation in the MockIntegration section says that "The MockIntegration factory provides an API to build mocks for Spring Integration beans that are parts of the integration flow (MessageSource, MessageProducer, MessageHandler, and MessageChannel).You can use the target mocks during the configuration phase as well as in the target test method to replace the real endpoints before performing verifications and assertions". I haven't found any examples using MessageProducer in the spring integration documentation and the Spring Integration Samples repository on github. I wrote test to try replace ImapIdleChannelAdapter
@SpringBootTest(classes = ImapConfiguration.class)
@Import({ReceiverTestConf.class})
@SpringIntegrationTest(noAutoStartup = "inboundChannelAdapter")
public class ImapMailReceiverTest {
@Captor
ArgumentCaptor<ReceivedMail> emailCaptor = ArgumentCaptor.forClass(ReceivedMail.class);
@MockBean
TestEmailHandler emailHandlerTestImpl;
@Autowired
TestImapReceiver imapReceiver;
@Autowired
MockIntegrationContext mockIntegrationContext;
@Test
@SneakyThrows
void receive() throws MessagingException {
Mockito.doNothing().when(emailHandlerTestImpl).handle(Mockito.any());
MessageSource<MimeMessage> message = () -> {
return new GenericMessage<>("testMessage");
};
this.mockIntegrationContext.substituteMessageSourceFor("imapIdleChannelAdapter", MockIntegration.mockMessageSource(message));
idleChannelAdapter.start();
await().atMost(1, TimeUnit.SECONDS).untilAsserted(() -> {
Mockito.verify(emailHandlerTestImpl, Mockito.times(1)).handle(emailCaptor.capture());
List<ReceivedMail> result = emailCaptor.getAllValues();
Assertions.assertEquals(1, result.size());
}
);
}
When I run the test, I am getting the exception.
Bean named 'imapIdleChannelAdapter' is expected to be of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' but was actually of type 'com.test.emailadapter.imap.InternalImapIdleChannelAdapter'
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'imapIdleChannelAdapter' is expected to be of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' but was actually of type 'com.test.emailadapter.imap.InternalImapIdleChannelAdapter'
at app//org.springframework.beans.factory.support.AbstractBeanFactory.adaptBeanInstance(AbstractBeanFactory.java:417)
at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:398)
at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:217)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:157)
at app//org.springframework.integration.test.context.MockIntegrationContext.substituteMessageSourceFor(MockIntegrationContext.java:142)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信文档中的句子需要一些改进。我绝对记得,有一些野心可以嘲笑流程中的一切。因此,我们在那里提到了
MessageProducer
和MessageChannel
。但是,实际上,事实证明,我们不需要模拟消息通道,因为它们可以提供Chander Interceptor
来验证流程中与通道的各种交互。MessageProducer
也毫无意义地模拟,因为您可以将测试消息发射到该生产者将在生产中产生的频道中。因此,到目前为止,您需要的只是在测试之前停止此MessageProducer
并在测试中处理其频道。我看到您已经为您的测试类做了适当的
noautostartup =“ InboundChannelAdapter”
。由于您的流程中没有声明的频道,因此该频道是由框架自动创建的,该框架具有名称的模式:
[IntegrationFlow.BeanName] .Channel#[ChannelNameIndex]
。因此,您的integrationFlows.from(Adapter)
的输出通道是directChannel
,带有getflow.channel#0
bean name。请考虑提出GH问题,因此我们将改进该
模型集成
的文档。I believe the sentence in the doc needs some improvements. I definitely remember that there were some ambitions to be able mock everything in the flow. Therefore we mention over there a
MessageProducer
andMessageChannel
as well. However in practice it turns out that we don't need to mock message channels since they can be supplied withChannelInterceptor
to verify various interaction with the channel in the flow.The
MessageProducer
is also pointless to mock since you simply can emit a test message into the channel this producer is going to produce in the production. So, what you need so far is just stop thisMessageProducer
before the test and deal with its channel in the test already.I see you already do a proper
noAutoStartup = "inboundChannelAdapter"
for your test class.Since you don't have channel declared in your flow, the channel is auto-created by the framework with the pattern for name:
[IntegrationFlow.beanName].channel#[channelNameIndex]
. So, the output channel for yourIntegrationFlows.from(adapter)
is aDirectChannel
with agetFlow.channel#0
bean name.Please, consider to raise a GH issue, so we will improve the doc for that
MockIntegration
.