我想对我的应用程序进行端到端测试,并且需要确保骆驼路线可以正常工作。我使用NotifyBuilder来确保消息已完成,并且由于消耗消息会花费一些时间,因此我想让它处理30秒(但是如果消息尽快完成,则不应等待),然后继续进行验证。这可以正常工作,但是...但是不幸的是,NotifyBuilder有时对消息完成没有反应,但是我的日志消息指出所有必需的步骤都已完成。这种情况并非总是发生,但有规律地发生,平均是十次运行两次。有趣的是,我在几种测试中都使用了这种方法,但是它们在此问题上随机失败,通常一次一次失败(其他所有一次都通过)。

稍微调试一下Camel代码后,我注意到由于某些原因,即使已触发相应的事件,也未调用方法org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchangeCompletedorg.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchange

我还注意到,当单独运行测试(一次运行一次)时,一切都按预期工作。同样,当我两次发送一条相同的消息时,NotifyBuilder仅对第二条消息调用org.apache.camel.builder.NotifyBuilder.EventPredicateSupport#onExchangeCompleted

我使用骆驼2.18.3和JDK 8u60。操作系统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 -->

最佳答案

我遇到了同样的问题,问题在于每次测试后都无法正确重置骆驼上下文。可以使用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());
    }

关于java - NotifyBuilder在重复运行中的行为不一致,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45480313/

10-10 16:33