我想对我的应用程序进行端到端测试,我需要确保Camel路由正常工作。我使用NotifyBuilder来确保消息已完成,并且由于消费消息需要一些时间我想让它处理30秒(但如果消息很快就完成它不应该等待)然后继续验证。这很好,但是......但不幸的是NotifyBuilder不时会对消息完成做出反应,但是我的日志消息说明所有必需的步骤都已完成。这种情况并非总是发生,而是平均每次发生10次。有趣的是,我在几个测试中使用了这样的方法,并且它们随机地失败了这个问题,通常一次一个(所有其他的都通过)。
稍微调试Camel代码之后,我注意到由于某些原因未调用方法org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchangeCompleted
和org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchange
,即使已触发相应的事件。
另外我注意到,当单独运行测试时(一次一个),一切都按预期工作。此外,当我两次发送一条相同的消息时,NotifyBuilder仅针对第二条消息调用org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchangeCompleted
。
我使用camel 2.18.3和JDK 8u60。 OS Linux Mint 17和CentOS(在Windows上似乎一切正常)。测试在命令行中通过gradle任务在单个线程中执行。
有没有人知道这种行为的原因是什么?
提前致谢。
这是我的测试类代码和驼峰配置:
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 -->
答案 0 :(得分:1)
我遇到了同样的问题,问题在于每次测试后都无法正确重置骆驼上下文。可以使用Springboot @DirtiesContext
注释解决此问题。
我遇到的问题是类似的,测试通过不一致,并且由于随机测试失败(即使它们在本地通过),导致Jenkins的构建失败。问题是在每个单元测试中使用的Camel上下文在每次测试后并不总是被重置。导致骆驼进入轮询循环,并在NotifyBuilder.matchsMockWaitTime()
超时时失败。
通过放置
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
在测试类顶部的,在运行每个测试后重置使用的上下文。这样可以确保您的骆驼上下文在运行多个测试时不会尝试使用旧路由,从而导致轮询循环。
@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());
}