2013-11-18 1 views
2

단위 테스트에서 Exception이 발생한다는 것을 시뮬레이트하고 싶습니다.인터셉터를 사용할 때 카멜 예외 처리 동작

doTry/doCatch -block 때문에 "mock : count"엔드 포인트에서 하나의 메시지를 수신 할 것으로 예상됩니다. 왜 이런 일이 일어나지 않고 왜 Exception은 일반 onException- 블록으로 처리됩니까?

import org.apache.camel.LoggingLevel; 
import org.apache.camel.builder.AdviceWithRouteBuilder; 
import org.apache.camel.builder.RouteBuilder; 
import org.apache.camel.component.mock.MockEndpoint; 
import org.apache.camel.test.junit4.CamelTestSupport; 
import org.apache.cxf.binding.soap.SoapFault; 
import org.junit.Test; 
import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.Text; 

public class TestClass extends CamelTestSupport { 
    @Override 
    protected RouteBuilder createRouteBuilder() throws Exception { 
     return new RouteBuilder() { 
     @Override 
     public void configure() throws Exception { 
      onException(Exception.class) 
        .log(LoggingLevel.INFO, "outer catch") 
        .handled(true); 

      from("direct:start") 
        .doTry() 
        .to("mock:exception") 

        .doCatch(Exception.class) 
        .log(LoggingLevel.INFO, "inner catch") 
        .to("mock:count") 
        .end(); 
     } 
     }; 
    } 

    @Test 
    public void testBlaat() throws Exception { 
     final SoapFault soapFault = new SoapFault("Something clearly went wrong", SoapFault.FAULT_CODE_CLIENT); 
     Element detail = soapFault.getOrCreateDetail(); 
     Document doc = detail.getOwnerDocument(); 
     Text tn = doc.createTextNode("Fault details"); 
     detail.appendChild(tn); 

     context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() { 
     @Override 
     public void configure() throws Exception { 
      interceptSendToEndpoint("mock:exception").throwException(new Exception("test")); 
     } 
     }); 

     template.sendBody("direct:start", "start"); 

     MockEndpoint endpoint = getMockEndpoint("mock:count"); 
     endpoint.expectedMessageCount(1); 

     assertMockEndpointsSatisfied(); 

    } 
} 

답변

4

그것은 서로 다른 채널에 있기 때문에 경로가 AdviceWithRouteBuilder에 의해 차단 될 때 AdviceWithRouteBuilder에서 발생한 예외가 RouteDefinitiondoTry/doCatch에 의해 보이지 않는 것으로 나타났다. 이 문제를 해결하는 방법은 엔드 포인트에 대한 모의를 사용하고 모의에서 예외를 발생하는 것입니다

getMockEndpoint("mock:exception").whenAnyExchangeReceived(new 
Processor() { 

      @Override 
      public void process(Exchange exchange) throws Exception { 
       throw new Exception("fail me"); 
      } 
     }); 

참조 : 그것은 낙타 2.10에서 해결 https://issues.apache.org/jira/browse/CAMEL-6300 : http://camel.465427.n5.nabble.com/question-about-exception-handling-behavior-td5743489.html

는 또한 JIRA에서이 문제를보고 .5 및 다른 최신 버전.

0

왜 이런 일이 발생하는지 잘 모르겠지만 아이디어가 있습니다. 테스트 케이스에 도달하기 전에 컨텍스트가 시작되고 있다고 생각합니다. 아마도 인터셉터가 너무 늦게 설정되어있을 수 있습니다. 당신은 다음을 시도해 볼 수 있습니까?

@Override 
public boolean isUseRouteBuilder() { 
    return false; 
} 

그럼 대신 createRouteBuilder를 오버라이드 (override)의 context.addRoutes(new RouteBuilder(){ .. })로 경로를 정의하는 일반적인 방법을 사용

이 방법을 추가합니다. 또한 여기에 인터셉터를 정의하십시오.

경로 및 인터셉터를 구성한 후 테스트 사례에 context.start()을 실행하십시오. 시도해보고 작동하는지 알려주십시오.

UPDATE : 재정 isUseRouteBuilder이 필요하지 않습니다.

UPDATE2 :

나는 몇 가지 테스트를 실행 한 나는이 같은 행동을보고하고있다. onException은 항상 doCatch 전에 트리거됩니다. 또한 handledtrue으로 설정하면 예외가 전파되지 않고 doCatch 블록에 도달하지 않습니다. 제가 적용되지 않는 오류 처리기를 이해할 doTry doCatch doFinally의 문서를 바탕으로

(사용하는 경우 doTry .. doCatch .. doFinally 다음 정규 낙타 오류 처리기는 적용되지 않습니다)하지만 오류 처리기와 onException 보인다 동일하지 않습니다.

또한이 발견했습니다 : how to handle exception or fault in multiple routes 당신을 위해 도움이 될 수 있습니다.

마지막으로 한가지 :

context.addRoutes(new RouteBuilder() { 
     @Override 
     public void configure() throws Exception { 
      interceptSendToEndpoint("mock:exception").throwException(new Exception()); 

      onException(Exception.class).process(new Processor() { 
       @Override 
       public void process(Exchange exchange) throws Exception { 
        System.out.println("from onException"); 

       } 

      }).handled(false); 

      from("direct:start") 
      //.errorHandler(noErrorHandler()) 
      .doTry() 
       .to("mock:exception") 
      .doCatch(Exception.class) 
       .process(new Processor() { 
        @Override 
        public void process(Exchange exchange) throws Exception { 
         System.out.println("from doCatch"); 
        } 
       }) 
       .to("mock:count") 
      .end(); 


     } 
    }); 

이 도움을합니까 : 동일한 RouteBuilder에 인터셉터를 정의 할 수 있습니다?

+0

isUseRouteBuilder 재정의를 추가하지 않은 경우에만 작동합니다. –

+0

나는 그 방법을 무시하는 것이 필요하다고 생각했다. – hveiga

+0

불행히도 여전히 작동하지 않습니다. .markRollBackOnly() 및 .handled (true)를 주석 처리하면 작동하지만 모든 예외가 먼저 해당 블록을 통과 한 것처럼 보입니다. –