2012-03-02 85 views
3

我有以下路由。在單元測試中,由於我沒有可用的FTP服務器,我想使用駱駝的測試支持併發送無效的消息到"ftp://hostname/input"並驗證它失敗並路由到"ftp://hostname/error"用Apache Camel單元測試FTP客戶端

我經歷了主要談論使用「模擬:」端點的文檔,但我不確定如何在這種情況下使用它。

public class MyRoute extends RouteBuilder 
{ 
    @Override 
    public void configure() 
    { 
     onException(EdiOrderParsingException.class).handled(true).to("ftp://hostname/error"); 

     from("ftp://hostname/input") 
      .bean(new OrderEdiTocXml()) 
      .convertBodyTo(String.class) 
      .convertBodyTo(Document.class) 
      .choice() 
      .when(xpath("/cXML/Response/Status/@text='OK'")) 
      .to("ftp://hostname/valid").otherwise() 
      .to("ftp://hostname/invalid"); 
    } 
} 

回答

9

正如本說你可以設置一個FTP服務器並使用真實的組件。可以嵌入FTP服務器,也可以在內部安裝FTP服務器。後者更像是一個集成測試,你可能有一個專門的測試環境。

駱駝在其測試工具包中非常靈活,如果你想構建一個不使用真實FTP組件的單元測試,那麼你可以在測試之前替換它。例如,在您的示例中,您可以將路由的輸入端點替換爲直接端點,以便將消息發送到路由。然後,您可以使用攔截器攔截髮送到ftp端點並繞行該消息。

對部分測試套件的建議提供了以下功能:http://camel.apache.org/advicewith.html。駱駝在行動書中的第6章也討論過這個問題,比如第6.3節,它討論了模擬錯誤。

在您的例子,你可以做一些類似的

public void testSendError() throws Exception { 
    // first advice the route to replace the input, and catch sending to FTP servers 
    context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() { 
     @Override 
     public void configure() throws Exception { 
      replaceFromWith("direct:input); 

      // intercept valid messages 
      interceptSendToEndpoint("ftp://hostname/valid") 
       .skipSendToOriginalEndpoint() 
       .to("mock:valid"); 

      // intercept invalid messages 
      interceptSendToEndpoint("ftp://hostname/invalid") 
       .skipSendToOriginalEndpoint() 
       .to("mock:invalid"); 
     } 
    }); 

    // we must manually start when we are done with all the advice with 
    context.start(); 

    // setup expectations on the mocks 
    getMockEndpoint("mock:invalid").expectedMessageCount(1); 
    getMockEndpoint("mock:valid").expectedMessageCount(0); 

    // send the invalid message to the route 
    template.sendBody("direct:input", "Some invalid content here"); 

    // assert that the test was okay 
    assertMockEndpointsSatisfied(); 
} 

駝2.10開始,我們會做出攔截,並使用建議用嘲笑的時候更容易一些。以及我們正在引入一個存根組件。 http://camel.apache.org/stub

+0

我把端點定義爲「ftp:// host/incoming?move = processed」。我如何確保文件已被移至「已處理」目錄?我將如何與此相提並論? Camel是否爲「已處理」創建了一個單獨的端點? – 2012-03-05 00:43:11

+0

我也有兩個來自(..)的定義(1定義了處理PO的路由,另一個定義了處理髮票的路由),在這種情況下replaceFromWith(...)是否替換了這兩個路由? – 2012-03-05 00:59:19

+0

我想出了第二條評論的答案。我需要在context.getRouteDefinitions()。get(0)方法中使用適當的索引。請幫我評論1。 – 2012-03-06 02:26:06

1

看看這個單元測試和那些在同一目錄...他們會告訴你如何站立本地FTP服務器進行測試,以及如何使用CamelTestSupport驗證反對它,等場景..

例子的單元測試...

https://svn.apache.org/repos/asf/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FromFileToFtpTest.java

延伸此測試支持類...

https://svn.apache.org/repos/asf/camel/trunk/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/FtpsServerTestSupport.java

3

看看MockFtPServer

<dependency> 
    <groupId>org.mockftpserver</groupId> 
    <artifactId>MockFtpServer</artifactId> 
    <version>2.2</version> 
    <scope>test</scope> 
</dependency> 

有了這一個可以模擬各種樣的權限問題等行爲:

例子:

fakeFtpServer = new FakeFtpServer(); 

fakeFtpServer.setServerControlPort(FTPPORT); 

FileSystem fileSystem = new UnixFakeFileSystem(); 
fileSystem.add(new DirectoryEntry(FTPDIRECTORY)); 
fakeFtpServer.setFileSystem(fileSystem); 
fakeFtpServer.addUserAccount(new UserAccount(USERNAME, PASSWORD, FTPDIRECTORY)); 

... 

assertTrue("Expected file to be transferred", fakeFtpServer.getFileSystem().exists(FTPDIRECTORY + "/" + FILENAME)); 
0

在我們的項目,我們不創建模擬FTP服務器來測試路線但是我們使用的屬性可以被一個file駱駝組件替代,用於本地開發和單元測試。

您的代碼應該是這樣的:

public class MyRoute extends RouteBuilder 
{ 
    @Override 
    public void configure() 
    { 
     onException(EdiOrderParsingException.class) 
      .handled(true) 
      .to("{{myroute.error}}"); 

     from("{{myroute.input.endpoint}}") 
      .bean(new OrderEdiTocXml()) 
      .convertBodyTo(String.class) 
      .convertBodyTo(Document.class) 
      .choice() 
       .when(xpath("/cXML/Response/Status/@text='OK'")) 
       .to("{{myroute.valid.endpoint}}}") 
       .otherwise() 
       .to("{{myroute.invalid.endpoint}}"); 
    } 
} 

並在本地和系統測試中,我們使用一個文件終點在屬性文件中聲明:

myroute.input.endpoint=file:/home/user/myproject/input 
myroute.valid.endpoint=file:/home/user/myproject/valid 
myroute.invalid.endpoint=file:/home/user/myproject/invalid 
myroute.error=file:/home/user/myproject/error 

或一個JUnit CamelTestSupport可以使用用於設置要覆蓋的屬性的useOverridePropertiesWithPropertiesComponent方法。

作爲替代方案,你也可以使用「直接」路線,而不是,但你可以錯過可以通過單元測試來測試一些文件選項。

,我們只通過設置這樣的性能測試與實際系統的FTP連接:

myroute.input.endpoint=ftp://hostname/input 
myroute.valid.endpoint=ftp://hostname/valid 
myroute.invalid.endpoint=ftp://hostname/invalid 
myroute.error=ftp://hostname/error 

有了這個,你也可以有e.g生產服務器將從集成測試環境中區分不同的配置。屬性對生產環境

例子:

myroute.input.endpoint=ftp://hostname-prod/input 
myroute.valid.endpoint=ftp://hostname-prod/valid 
myroute.invalid.endpoint=ftp://hostname-prod/invalid 
myroute.error=ftp://hostname-prod/error 

在我看來,這是完全可以使用的文件端點,以簡化的JUnit代碼,它會測試路線,而不是連接。

測試連接更像是一個集成測試,並應與真正的外部系統連接真實服務器上執行(你的情況的FTP服務器,但也可以是其他終端/系統以及)。

通過使用屬性,你還可以配置不同的URL的每個環境(例如:我們有3個的測試環境和一個生產環境,都具有不同的端點)。