在测试Camel路线时,如何正确使用Mocks



我正在尝试编写一个Camel测试,该测试旨在确保基于内容的路由器正确路由XML文件。以下是我的blueprint.xml中的要点和路线:

<endpoint uri="activemq:queue:INPUTQUEUE" id="jms.queue.input" />
<endpoint uri="activemq:queue:QUEUE1" id="jms.queue.1" />
<endpoint uri="activemq:queue:QUEUE2" id="jms.queue.2" />
<route id="general-jms.to.specific-jms">
    <from ref="jms.queue.input" />
    <choice>
      <when>
        <xpath>//object-type = '1'</xpath>
        <log message="Sending message to queue: QUEUE1" />
        <to ref="jms.queue.1" />
      </when>
      <when>
        <xpath>//object-type = '2'</xpath>
        <log message="Sending message to queue: QUEUE2" />
        <to ref="jms.queue.2" />
      </when>
      <otherwise>
        <log message="No output was able to be determined based on the input." />
      </otherwise>
    </choice>
</route>

现在,我所要做的就是发送一个<object-type>为1的示例源文件,并验证它是否路由到了正确的队列(QUEUE1),并且是正确的数据(应该只将整个XML文件发送到QUEUE1中)。这是我的测试代码:

public class RouteTest extends CamelBlueprintTestSupport {
    @Override
    protected String getBlueprintDescriptor() {
        return "/OSGI-INF/blueprint/blueprint.xml";
    }
    @Override
    public String isMockEndpointsAndSkip() {
        return "activemq:queue:QUEUE1";
    }
    @Test
    public void testQueue1Route() throws Exception {
        getMockEndpoint("mock:activemq:queue:QUEUE1").expectedBodiesReceived(context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue1-test.xml")));
        template.sendBody("activemq:queue:INPUTQUEUE", context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue1-test.xml")));
        assertMockEndpointsSatisfied();
    }
}

当我运行这个测试时,我看到我放在路由定义中的日志消息,说它正在将它发送到QUEUE1,但JUnit测试失败,并显示以下错误消息:java.lang.AssertionError:mock://activemq:queue:QUEUE1收到的消息计数。应为:<1> 但是是:<0>

有人能帮我理解我做错了什么吗?

我的理解是,Camel将自动模拟QUEUE1端点,因为我覆盖了isMockEndpointsAndSkip()并提供了QUEUE1终结点uri。我认为这意味着我应该能够在getMockEnpoint()方法中使用该端点,只需在uri的开头添加"mock:"即可。然后我应该有一个模拟端点,我可以对它设置期望值(即必须有输入文件)。

如果我有什么不清楚的地方,请告诉我,我们非常感谢您的帮助!

解决方案是使用CamelTestSupport.replaceRouteFromWith

这个方法完全没有任何文档,但当像这样调用它时,它对我有效:

public class FooTest extends CamelTestSupport {
    @Override
    public void setUp() throws Exception {
        replaceRouteFromWith("route-id", "direct:route-input-replaced");
        super.setUp();
    }
    // other stuff ...
}

这也将阻止路由的from目的地的原始消费者的启动。例如,这意味着在测试带有activemq使用者的路由时,不再需要运行activemq实例。

在做了很长一段时间之后,我想出的唯一有效的解决方案是在我的测试类中使用createRouteBuilder()方法,在blueprint.xml文件中定义的路由末尾添加一个到模拟端点的路由。然后,我可以检查那个模拟的端点是否符合我的期望。下面是我为测试类编写的最后一段代码。蓝图XML保持不变。

public class RouteTest extends CamelBlueprintTestSupport {
@Override
protected String getBlueprintDescriptor() {
    return "/OSGI-INF/blueprint/blueprint.xml";
}
@Test
public void testQueue1Route() throws Exception {
    getMockEndpoint("mock:QUEUE1").expectedBodiesReceived(context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue1-test.xml")));
    template.sendBody("activemq:queue:INPUTQUEUE", context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue1-test.xml")));
    assertMockEndpointsSatisfied();
}
@Test
public void testQueue2Route() throws Exception {
    getMockEndpoint("mock:QUEUE2").expectedBodiesReceived(context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue2-test.xml")));
    template.sendBody("activemq:queue:INPUTQUEUE", context.getTypeConverter().convertTo(String.class, new File("src/test/resources/queue2-test.xml")));
    assertMockEndpointsSatisfied();
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        public void configure() throws Exception {
            from("activemq:queue:QUEUE1").to("mock:QUEUE1");
            from("activemq:queue:QUEUE2").to("mock:QUEUE2");
        }
    };
}

}

虽然这个解决方案有效,但我不完全理解为什么我不能只使用isMockEndpointsAndSkip(),而不必在现有blueprint.xml路由的末尾手动定义一个新路由。我的理解是,用return "*";定义isMockEndpointsAndSkip()将为blueprint.xml文件中定义的所有端点注入模拟端点。然后你可以检查你对那些被嘲笑的端点的期望。但由于某种原因,这对我来说不起作用。

最新更新