Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 缓存上下文时MockIntegrationMessage不工作_Java_Spring_Spring Boot_Spring Integration_Spring Test - Fatal编程技术网

Java 缓存上下文时MockIntegrationMessage不工作

Java 缓存上下文时MockIntegrationMessage不工作,java,spring,spring-boot,spring-integration,spring-test,Java,Spring,Spring Boot,Spring Integration,Spring Test,我正在使用springintegration5.1.7.RELEASE,springboot2.1.7.RELEASE和springintegrationtest 5.0.11.RELEASE 作为测试的一部分,我正在尝试unittest一个IntegrationFlow,它执行对不同MessageHandlers的调用,因此我正在使用Spring集成测试中的MockIntegrationContext模拟它们 我的代码在Jenkins服务器上出现间歇性问题,这似乎与正在缓存的上下文有关。我有一

我正在使用
springintegration5.1.7.RELEASE
springboot2.1.7.RELEASE
springintegrationtest 5.0.11.RELEASE

作为测试的一部分,我正在尝试
unittest
一个
IntegrationFlow
,它执行对不同
MessageHandlers
的调用,因此我正在
使用
Spring集成测试中的
MockIntegrationContext
模拟它们

我的代码在Jenkins服务器上出现间歇性问题,这似乎与正在缓存的上下文有关。我有一个集成测试(
@SpringBootTest
),没有模拟,还有一个测试类专门用于模拟
IntegrationFlow
MessageHandlers

如果集成测试在之前运行并且缓存了上下文,则由
MockIntegrationContext
执行的设置似乎没有任何效果,并且调用底层
service activator
,即使日志显示它已被取消订阅,而mock已被订阅到频道

以下是轮询器和句柄端点的定义:

@配置
公共类FlowConfig{
@豆子
公共集成流文件流(){
返回IntegrationFlows.from(
Files.inboundAdapter(新文件(fileDir)).autoCreateDirectory(true).preventDuplicates(false),
e->e.poller(Pollers.fixedDelay(pollingFrequency)).id(“fileInboundSourceEndpoint”).get()
...
.handle(fileParseHandler,e->e.id(“fileParseHandlerEndpoint”))
...
.get()
}
}
以下是测试设置:

@RunWith(SpringRunner.class)
@ContextConfiguration(class=FlowConfig.class)
@SpringIntegrationTest
@使能集成
公共类流测试{
@自动连线
MockIntegrationContext mockIntegrationCtx;
@试验
public void test_fileFlow()引发IOException{
mockIntegrationCtx.substituteMessageHandlerFor(“fileParseHandlerEndpoint”,
MockIntegration.mockMessageHandler().handleNextAndReply(m->m));
新文件(fileDir+“test”).createNewFile();
}
}
这是两组不同的日志,分别来自一个不成功的测试执行和一个成功的测试执行:

2019-09-09 15:17:02.059  INFO 14462 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Removing {service-activator:fileParseHandlerEndpoint} as a subscriber to the 'fileFlow.channel#2' channel
2019-09-09 15:17:02.059  INFO 14462 --- [           main] o.s.integration.channel.DirectChannel    : Channel 'org.springframework.context.support.GenericApplicationContext@51f95f0d.fileFlow.channel#2' has 0 subscriber(s).
2019-09-09 15:17:02.059  INFO 14462 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : stopped fileParseHandlerEndpoint
2019-09-09 15:17:02.062  INFO 14462 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {message-handler:fileParseHandlerEndpoint} as a subscriber to the 'fileFlow.channel#2' channel
2019-09-09 15:17:02.062  INFO 14462 --- [           main] o.s.integration.channel.DirectChannel    : Channel 'org.springframework.context.support.GenericApplicationContext@51f95f0d.fileFlow.channel#2' has 1 subscriber(s).
2019-09-09 15:17:02.062  INFO 14462 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started fileParseHandlerEndpoint
...
2019-09-09 15:17:03.731 DEBUG 14462 --- [   scheduling-1] o.s.i.file.FileReadingMessageSource      : Added to queue: [/tmp/file]
2019-09-09 15:17:03.732 DEBUG 14462 --- [   scheduling-1] o.s.i.e.SourcePollingChannelAdapter      : Poll resulted in Message: GenericMessage [payload=/tmp/file, headers={file_originalFile=/tmp/file, id=4323b036-4edd-019e-2c61-6917c7970767, file_name=file, file_relativePath=file, timestamp=1568056623732}]
...
2019-09-09 15:17:03.732 DEBUG 14462 --- [   scheduling-1] o.s.integration.channel.DirectChannel    : preSend on channel 'fileFlow.channel#2', message: GenericMessage [payload=/tmp/file, headers={file_originalFile=/tmp/file, errorChannel=error_channel, id=af997a89-40d6-9024-65fc-7ab3883c329b, file_name=file, file_relativePath=file, timestamp=1568056623732}]
2019-09-09 15:17:03.732 DEBUG 14462 --- [   scheduling-1] o.s.i.handler.ServiceActivatingHandler   : ServiceActivator for [org.springframework.integration.handler.MethodInvokingMessageProcessor@7b4acdc2] (fileParseHandlerEndpoint) received message: GenericMessage [payload=/tmp/file, headers={file_originalFile=/tmp/file, errorChannel=error_channel, id=af997a89-40d6-9024-65fc-7ab3883c329b, file_name=file, file_relativePath=file, timestamp=1568056623732}]
[Fatal Error] file:1:1: Premature end of file.
我知道可能有一个组合的
@DirtiesContext
可以解决这个问题,但我仍然很难理解为什么
MockIntegrationContext
无法从缓存的上下文中模拟
MessageHandlers


是否有任何方法可以在不使用
@DirtiesContext
的情况下修复此问题?

首先,当您使用Spring Boot时,您需要依赖其版本管理。 此外,当使用Spring集成时,考虑使用<代码> Spring集成BOM<代码>导入。这样,您也不需要为单个模块指定版本

我的观点是,
springintegrationcore
springintegrationtest
有不同的版本。它们必须是一样的。否则,您可能会在运行时陷入混乱

现在谈谈这个问题

我认为这不是缓存问题

此测试套件的应用程序上下文开始与目标测试方法中的
mockIntegrationCtx.substituteMessageHandlerFor()
之间存在竞争条件

问题来自这样一个事实:您从
e.poller(Pollers.fixedDelay(pollingFrequency)
启动流。这是由
TaskScheduler
在后台处理的,并为您的测试套件生成独立于主线程的消息。这就是您观察到意外行为的原因

您可以使用类似于
autoStartup
操作的方法来解决此问题。
@SpringIntegrationTest
为您提供了以下功能:

/**
 * Specify a simple matching patterns ("xxx*", "*xxx", "*xxx*" or "xxx*yyy") for
 * {@link org.springframework.integration.endpoint.AbstractEndpoint}
 * bean names to mark them as {@code autoStartup = false}
 * during context initialization.
 * @return the endpoints name patterns to stop during context initialization
 * @see IntegrationEndpointsInitializer
 * @see org.springframework.util.PatternMatchUtils
 */
String[] noAutoStartup() default {};
所以,你喜欢这样:

@SpringIntegrationTest(noAutoStartup = "fileInboundSourceEndpoint")
然后在测试中自动连接通道适配器:

@自动连线 私有SourcePollingChannelAdapter fileInboundSourceEndpoint

然后在
substituteMessageHandlerFor()之后启动它:

this.fileInboundSourceEndpoint.start();

谢谢!这应该可以解决问题。快速提问:我在同一测试套件上有多个测试。我是否应该在每次测试后停止SourcePollingChannelAdapter,并仅在设置模拟后重新启动它?如果在每个测试方法中使用相同的流,那么确实需要在每次测试后重新停止它。不过,我会将所有内容都保存在一个t中est方法:对于相同的
SourcePollingChannelAdapter
,您有一个上下文,从性能角度来看,它更好。
this.fileInboundSourceEndpoint.start();