2014-05-19 13 views
5

Tôi có định nghĩa Tuyến đường Camel rất đơn giản chỉ bao gồm một số biến vị ngữ OnException để xử lý các ngoại lệ tương ứng và một số báo cáo đăng nhập.Tuyến đường thử nghiệm bằng cách sử dụng lời khuyênVới định nghĩa OnException

from("hazelcast:seda:someQueue") 
    .id("someQueueID") 
    .onException(CustomException.class) 
     .handled(true) 
     .log(LoggingLevel.WARN, "custom exception noticed") 
    .end() 
    .onException(IOException.class, FileNotFoundException.class) 
     .asyncDelayedRedelivery() 
     .redeliveryDelay(3*1000*60) // 3 Minutes 
     .maximumRedeliveries(3) 
     .log(LoggingLevel.WARN, "io exception noticed") 
    .end() 
    .onException(Exception.class) 
     .log(LoggingLevel.WARN, "general exception noticed") 
    .end() 

    .log("Starting route") 
    .bean(TestBean.class) 
    .log("Finished route"); 

bean chính nó là đơn giản quá, nó chỉ kiểm tra một tham số header và ném một ngoại lệ thích hợp

public class TestBean 
{ 
    @Handler 
    public void checkData(@Headers final Map<String, Object> headers) 
      throws CustomException, IOException, Exception 
    { 
     Integer testVal = (Integer)headers.get("TestValue"); 
     if (0 == testVal) 
      throw new CustomException("CustomException"); 
     else if (1 == testVal) 
      throw new IOException("IOException"); 
     else 
      throw new Exception("Exception"); 
    } 
} 

Vì đây thử nghiệm thiết lập chỉ là một phần nhỏ của một dự án lớn hơn nó nghe có vẻ ngớ ngẩn để làm điều đó như được trình bày ở đây, nhưng cốt lõi có ý định là sửa đổi redeliveryDelay tại thời điểm thử nghiệm như là một "bắt buộc" IOException sẽ không cần phải đợi 3 phút và do đó, để tăng tốc độ kiểm tra đơn vị một chút, độ trễ phân phối có thể được giảm xuống như 10 ms.

Để đạt được điều này thử nghiệm phương pháp của tôi thực hiện như sau:

@ContextConfiguration(classes = OnExceptionRouteTest.ContextConfig.class, loader = AnnotationConfigContextLoader.class) 
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) 
public class OnExceptionRouteTest extends CamelSpringTestSupport 
{ 
    @Override 
    protected AbstractApplicationContext createApplicationContext() 
    { 
     return new AnnotationConfigApplicationContext(ContextConfig.class) 
    } 

    @Configuration 
    public static class ContextConfig extends CamelConfiguration 
    { 
     @Override 
     protected void setupCamelContext(CamelContext camelContext) throws Exception 
     { 
      super.setupCamelContext(camelContext); 
      camelContext.addComponent("hazelcast", new StubComponent()); 
      // some other unnecessary stuff 
     } 

     @Override 
     public List<RouteBuilder> routes() 
     { 
      final List<RouteBuilder> list = new ArrayList<>(); 
      list.add(new OnExceptionRoute()); 
      return list; 
     } 
    } 

    @Override 
    public boolean isUseAdviceWith() 
    { 
     return true; 
    } 

    @Test 
    public void testIOException() 
    { 
     context.getRouteDefinition("someQueueID") 
       .adviceWith(context, new AdviceWithRouteBuilder() 
       { 
        @Override 
        public void configure() throws Exception 
        { 
         this.weaveByType(OnExceptionDefinition.class) 
          .selectIndex(1) 
          .replace() 
           .onException(IOException.class, FileNotFound.class) 
            .asyncDelayedRedelivery() 
            .redeliveryDelay(10) 
            .maximumRedeliveries(3) 
            .log("modified io exception noticed") 
            .to("mock:ioError") 
           .end(); 
          ... 
          mockEndpoints(); 
        } 
       }); 
     context.start(); 
     MockEndpoint ioErrorEndpoint = getMockEndpoint("mock:ioError"); 
     ... 
     ioErrorEndpoint.setExpectedMessageCount(1); 
     ... 

     Map<String, Object> headers = new HashMap<>(); 
     headers.put("TestValue", new Integer(1)); 
     template.sendBodyAndHeaders("hazelcast:seda:someQueue", new Object(), headers); 

     ... 
     ioErrorEndpoint.assertIsSatisfied(); 
     ... 
    } 
} 

Đây là bài kiểm tra chỉ thay thế các phân khúc onException của IOException đầu tiên giảm sự chậm trễ trả tàu từ 3 phút đến 10 ms và thêm một điểm cuối giả lập ở cuối. Tuy nhiên khi tôi cố gắng chạy thử nghiệm đơn vị tôi sẽ nhận được ngoại lệ sau đây:

java.lang.IllegalArgumentException: The output must be added as top-level on the route. Try moving OnException[[class java.io.IOException, class java.io.FileNotFoundException] -> []] to the top of route. 

Tuy nhiên, các ví dụ trong official documentation, như xa như tôi hiểu chúng một cách chính xác, rất giống nhau. Tôi cũng đã cố gắng tra cứu định nghĩa ngoại lệ thông qua một vị từ đã xác định ID và phương thức tương ứng của nó là weaveById() hoặc thông qua phương thức weaveByToString() nhưng không có kết quả nào khác. Tôi cũng đã cố gắng để loại bỏ các định nghĩa ngoại lệ thông qua weaveByType(OnExceptionDefinition.class).selectIndex(1).remove(); và thêm phần OnException qua weaveAddFirst().onException(...).async...; nhưng với cùng một kết quả.

Tuy nhiên, việc thêm điểm cuối lỗi giả định có thể thông qua f.e. weaveByToString("Log[io exception noticed]").after().to("mock:ioError");

Vì vậy, bất kỳ mẹo nào để sửa đổi trên khối Ngoại lệ hoặc phân phối lạiDelay cho các thử nghiệm đơn vị đều được hoan nghênh.


@Edit: Tôi cũng đã cố gắng để di chuyển tại các tờ khai onException trên định nghĩa đường (from(...)) theo đề nghị của thông điệp ngoại lệ và điều này cũng là trường hợp ưu tiên trong Camel của exception samples. Tuy nhiên, khi thực hiện điều này, tất cả các thử nghiệm (ngay cả những thử nghiệm hoạt động) đều không thành công như một NullPointerException trên context.getRouteDefinition("someQueueID").adviceWith(context, new AdviceWithRouteBuilder() {... }); vì rõ ràng là không thể tìm thấy tuyến đường nữa. Tôi nghi ngờ rằng đây là một vấn đề IntelliJ vì cả hai lớp đều nằm trong cùng một dự án và do đó việc sửa đổi lộ trình sẽ được hiển thị cho lớp thử nghiệm.

phiên bản Camel sử dụng: 2.13.0, IntelliJ IDEA 13.1.2


@ Edit2: Đối với một số lý do context.getRouteDefinitions("someQueueID") lợi nhuận null nếu các yếu tố OnException được định nghĩa bên ngoài của khối from, trong khi con đường chung có thể thu được thông qua context.getRouteDefinitions().get(0) - mặc dù, ngoại lệ cho biết rằng phần OnException cần được thêm làm phần tử cấp cao nhất vẫn còn.

+1

Một tùy chọn khác là thực hiện phân phối lại (và có thể nhiều cài đặt khác) một thuộc tính, và sau đó có tệp thuộc tính sản xuất + tệp thuộc tính thử nghiệm, với các giá trị khác nhau cho phù hợp với nhu cầu của bạn môi trường. –

+0

@SteveHarrington Mặc dù đề xuất của bạn với các giá trị thuộc tính tiêm vào các trường này hoạt động, điều này không giải quyết vấn đề cốt lõi cho lời khuyênVới kết hợp với các khối onException theo ý kiến ​​của tôi. Tuy nhiên, tôi muốn chấp nhận đề xuất của bạn như một câu trả lời nếu bạn sẵn sàng đăng câu trả lời. –

Trả lời

4

Khi sử dụng Java DSL, id của tuyến đường được đặt bằng phương pháp .routeId(), không phải .id() như bạn đã mã hóa ở trên. Điều đó có thể giúp bạn với các mối quan tâm adviceWith của bạn.

Thay vì mã hóa cứng độ trễ thử lại, cách tiếp cận tốt hơn là đặt cấu hình chậm trễ bằng các thuộc tính. Xem tài liệu xung quanh phương pháp useOverridePropertiesWithPropertiesComponent() trên lớp học CamelSpringTestSupport của bạn.

EDIT

Bạn không cần phải dệt mệnh đề onException, chỉ cần nêu một hình mới. Dưới đây là ví dụ hoàn chỉnh:

import org.apache.camel.builder.AdviceWithRouteBuilder; 
import org.apache.camel.builder.RouteBuilder; 
import org.apache.camel.test.junit4.CamelTestSupport; 

public class DummyTest extends CamelTestSupport{ 
    @Override 
    protected RouteBuilder createRouteBuilder() throws Exception { 
     return new RouteBuilder(){ 
      @Override 
      public void configure() throws Exception { 

       from("direct://start") 
        .routeId("myroute") 
        .onException(Exception.class) 
         .id("myException") 
         .continued(true) 
        .end() 
        .throwException(new Exception()) 
        .to("mock:end"); 
      } 
     }; 
    } 

    @org.junit.Test 
    public void doTest() throws Exception{ 
     context.getRouteDefinition("myroute").adviceWith(context, new AdviceWithRouteBuilder(){ 
      @Override 
      public void configure() throws Exception { 
       context.getRouteDefinition("myroute") 
        .onException(Exception.class).setBody(constant("adviceWith")).continued(true); 
      }}); 
     context.start(); 
     template.sendBody("direct://start", "original"); 
     String bodyAtEndOfExchange = getMockEndpoint("mock:end") 
       .getExchanges().get(0).getIn().getBody(String.class); 
     assertEquals("adviceWith", bodyAtEndOfExchange);   
     context.stop(); 
    } 

    @Override 
    public boolean isUseAdviceWith() { 
     return true; 
    } 
} 
+0

Tôi đã tìm ra vấn đề liên quan đến '.id (...)' và '.routeId (...)' nhưng cảm ơn bạn đã chỉ ra nó ở đây vì tôi đã không cập nhật bài đăng kể từ đó. Tôi cũng đã định cấu hình độ trễ thông qua các thuộc tính như đã được đề xuất bởi @SteveHarrington. Mặc dù điều này đã khắc phục được vấn đề của sự cố gắng kiểm tra cụ thể, chủ đề thực tế mặc dù vẫn còn - cách tư vấn cho khối onException đúng cách? Tất nhiên, 'inOnly' và 'to' có thể bị bắt bằng cách sử dụng interceptor, nhưng nếu chúng ta muốn thêm thứ gì đó vào giữa đường và không sử dụng id. Bạn không chắc liệu Camel 2.15+ có hỗ trợ tốt hơn hay không, hãy thử lại –

Các vấn đề liên quan