Java NotifyBuilder在重复运行时的行为不一致
我想对我的应用程序进行端到端测试,我需要确保驼峰路线工作正常。我使用NotifyBuilder来确保消息已完成,并且由于使用消息需要一些时间,我希望让消息处理30秒(但如果消息完成得更快,则不应等待),然后继续验证。这很好,但是。。。但不幸的是,NotifyBuilder有时在消息完成时不会做出反应,但我的日志消息表明所有必需的步骤都已完成。这种情况并不总是发生,但有规律地发生,平均10次中有2次。有趣的是,我在几个测试中使用了这样的方法,但它们在这个问题上随机失败,通常是一次一个(所有其他测试都通过) 在调试Camel代码之后,我注意到由于某些原因,Java NotifyBuilder在重复运行时的行为不一致,java,apache-camel,activemq,Java,Apache Camel,Activemq,我想对我的应用程序进行端到端测试,我需要确保驼峰路线工作正常。我使用NotifyBuilder来确保消息已完成,并且由于使用消息需要一些时间,我希望让消息处理30秒(但如果消息完成得更快,则不应等待),然后继续验证。这很好,但是。。。但不幸的是,NotifyBuilder有时在消息完成时不会做出反应,但我的日志消息表明所有必需的步骤都已完成。这种情况并不总是发生,但有规律地发生,平均10次中有2次。有趣的是,我在几个测试中使用了这样的方法,但它们在这个问题上随机失败,通常是一次一个(所有其他测试
org.apache.Camel.builder.NotifyBuilder.EventPredicateSupport#onExchange completed
和org.apache.Camel.builder.NotifyBuilder.EventPredicateSupport#onExchange
方法不会被调用,即使触发了相应的事件
我还注意到,当单独运行测试(一次一个)时,一切都按预期进行。同样,当我两次发送一条相同的消息时,NotifyBuilder调用org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#OneExchangeCompleted
,仅针对第二条消息
我使用camel 2.18.3和jdk8u60。操作系统Linux Mint 17和CentOS(在Windows上似乎一切正常)。测试由命令行中的gradle任务在单个线程中执行
有人知道这种行为的原因是什么吗
提前谢谢
以下是我的测试类代码和camel配置:
public class EndToEndTest {
@Resource(name = "camelContext")
private CamelContext camelContext;
@Produce(uri = "activemq:fromQueueName")
private ProducerTemplate template;
@Test
public void testWithNotifyBuilder() {
NotifyBuilder notify = new NotifyBuilder(camelContext)
.whenCompleted(1)
.from("activemq:fromQueueName")
.create();
template.sendBody("{\"json\":\"example\"}");
assertTrue(notify.matches(30, TimeUnit.SECONDS));
// other verifications
}}
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<!-- other endpoints and beans -->
<endpoint id="fromEndpoint" uri="activemq:fromQueueName"/>
<route>
<from ref="fromEndpoint"/>
<unmarshal>
<custom ref="customMessageUnmarshaller"/>
</unmarshal>
<bean ref="customMessageConsumer"/>
<onException redeliveryPolicyRef="defaultRedeliveryPolicy">
<exception>java.net.SocketException</exception>
<exception>javax.jms.JMSException</exception>
<handled>
<constant>true</constant>
</handled>
</onException>
</route>
<!-- other routes -->
公共类结束测试{
@资源(name=“camelContext”)
私人背景;
@生成(uri=“activemq:fromQueueName”)
私有产品模板;
@试验
公共void testWithNotifyBuilder(){
NotifyBuilder notify=新的NotifyBuilder(上下文)
.完成时(1)
.from(“activemq:fromQueueName”)
.create();
sendBody(“{\'json\':\'example\'”);
assertTrue(notify.matches(30,TimeUnit.SECONDS));
//其他核查
}}
java.net.SocketException
javax.jms.jmsceception
真的
我遇到了同样的问题,问题是骆驼上下文在每次测试后没有正确重置。可以使用Springboot注释修复此问题 我遇到的问题与此类似,不一致的测试通过了,而Jenkins中的构建由于随机测试失败而失败(即使它们在本地通过)。问题在于,在每个单元测试中使用的驼峰上下文并不总是在每次测试后重置。导致camel进入轮询循环,并在
NotifyBuilder.matchsMockWaitTime()超时时失败
通过放置
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
在测试类的顶部,在每次测试运行后都会重置所使用的上下文。这可以确保您的camel上下文在运行多个测试时不会尝试使用旧路由,从而导致轮询循环
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = MyApplication.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class DeadChannelTest {
@Autowired
private CamelContext context;
@Autowired
private ProducerTemplate template;
@Test
public void testMoveFile() throws Exception {
// use NotifyBuilder to wait for the file to be routed
NotifyBuilder notify = new NotifyBuilder(context).whenDone(1).create();
// create a new file in the inbox folder with the name hello.txt and containing Hello World as body
template.sendBodyAndHeader("file://camel/route",
FileUtils.readFileToString(new File(TestPath), "UTF-8"),
Exchange.FILE_NAME,
"testError.log");
// notifier will wait for the file to be processed
// and if that never happen it will time out after 10 seconds (default mock timeout)
assertTrue(notify.matchesMockWaitTime());
// test the file was moved
File target = new File(ErrorFolder + "/testError.log");
assertTrue("File should have been moved", target.exists());
}
您是否尝试过将谓词的顺序更新为.from(“activemq:fromQueueName”)。完成时(1)
?您是否可以稍微改进一下您的答案,例如您是如何使用它的,以及您将此注释添加到了何处?这将使未来的读者更清楚地了解如何解决类似问题。谢谢,这是一个非常好的答案:)。