2011-04-14 128 views
17

假设我有在独立的RouteBuilder类中创建的路由。它看起来像:从JMS队列如何在Apache Camel中测试生产路线?

  • 抢消息
  • 做一些转换,验证等
  • 根据验证结果转发到特定的JMS队列和保存东西在DB

我会就像单元测试这条路线一样,没有JMS代理,也没有数据库。我知道我可以嘲笑我的处理器实现,但这还不够。我不想改变这条路线(让我们假设我在jar文件中得到了这个类)。据我在Camel in Action(第6.2.6节)中所知道的,为了能够使用端点和其他东西的模拟,我需要改变我的路由端点定义(在本书的例子中,这是“mina:tcp://miranda“改为”mock:miranda“等)。

是否可以在完全隔离的情况下测试流而不更改路由定义? 如果我把我的RouteBuilder作为一个单独的类,我是否被迫以某种方式“复制”路径定义并手动更改它?它不是在测试错误的东西吗?

我对骆驼很陌生,对我来说,在拆散路线时能够进行单独的单元测试真的很酷。只是为了能够改变某些事物,运行小测试,观察结果等等。

回答

23

假设RouteBuilder类具有硬编码的端点,那么它有点难以测试。但是,如果RouteBuilder使用端点uris的属性占位符,那么您通常可以使用不同的端点uris集进行单元测试。正如骆驼书第六章所解释的那样。

如果他们被硬编码,那么你可以在你的单元测试功能使用建议如下所示:http://camel.apache.org/advicewith.html

在骆驼2.7,我们使我们能够操纵的路线容易得多,这样你就可以删除的零件,更换部件等这就是链接的编织材料谈论。

例如,要模拟向数据库端点发送消息,可以使用上面的代码并将其替换为另一个,然后将其发送给模拟。

在以前的版本中,你可以使用interceptSendToEndpoint技巧,这也包括在骆驼书(见第6.3.3节)

哦,你也可以替换模拟组件组件骆驼169页上显示现在2.8开始,模拟组件不会再抱怨它不知道的uri参数。这意味着在每个组件级别上用模拟替换组件更容易。

3

我有

<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent"> 
     <property name="location" value="classpath:shop.properties"/> 
    </bean> 

    <route> 
     <from uri="direct://stock"/> 
     <to uri="{{stock.out}}"/> 
    </route> 

在我的弹簧文件,然后在测试类路径我有被替换在运行时stock.out = XXXX上shop.properties所以我可以有不同的路由一个用于运行时,另一个用于测试

这是6.1中的一个更好的例子。在多种环境

0

6单元测试虽然你可以使用拦截和建议换出端点按克劳斯易卜生的 答案,我认为这是更好的,让你的路由接受Endpoint 实例,以使您的测试AREN” t耦合到您的生产端点URI。

例如,假设你有一个RouteBuilder,看起来像

public class MyRoute extends RouteBuilder { 
    @Override 
    public void configure() throws Exception { 
     from("http://someapi/someresource") 
     .process(exchange -> { 
      // Do stuff with exchange 
     }) 
     .to("activemq:somequeue"); 
    } 
} 

可以使人们有可能注入终点,像这样:

public class MyRoute extends RouteBuilder { 
    private Endpoint in; 
    private Endpoint out; 

    // This is the constructor your production code can call 
    public MyRoute(CamelContext context) { 
     this.in = context.getEndpoint("http://someapi/someresource"); 
     this.out = context.getEndpoint("activemq:somequeue"); 
    } 

    // This is the constructor your test can call, although it would be fine 
    // to use in production too 
    public MyRoute(Endpoint in, Endpoint out) { 
     this.in = in; 
     this.out = out; 
    } 

    @Override 
    public void configure() throws Exception { 
     from(this.in) 
     .process(exchange -> { 
      // Do stuff with exchange 
     }) 
     .to(this.out); 
    } 
} 

然后可以这样进行测试:

public class MyRouteTest { 
    private Endpoint in; 
    private MockEndpoint out; 
    private ProducerTemplate producer; 

    @Before 
    public void setup() { 
     CamelContext context = new DefaultCamelContext(); 

     this.in = context.getEndpoint("direct:in"); 
     this.out = context.getEndpoint("mock:direct:out", MockEndpoint.class); 
     this.producer = context.createProducerTemplate(); 
     this.producer.setDefaultEndpoint(this.in); 

     RouteBuilder myRoute = new MyRoute(this.in, this.out); 
     context.addRoutes(myRoute); 

     context.start(); 
    } 

    @Test 
    public void test() throws Exception { 
     this.producer.sendBody("Hello, world!"); 
     this.out.expectedMessageCount(1); 
     this.out.assertIsSatisfied(); 
    } 
} 

这具有以下优点:

  • 您的测试是非常简单和容易理解,并且甚至不需要延长CamelTestSupport或其他辅助类
  • 用手创建CamelContext所以你可以肯定,只有在测试路线创建
  • 测试不关心生产路线的URI
  • 你仍然有方便的硬编码的端点的URI到路径类,如果你想