2011-04-14 126 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到路徑類,如果你想