我有一個非常簡單的Camel路由定義,它只包含一些用於處理相應異常和一些日誌語句的OnException謂詞。使用adviceWith進行駱駝路由測試以及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本身也很簡單,它只是檢查頭參數,作爲這個測試的設置是一個大項目的一小部分,可能聽起來很傻拋出一個適當的異常
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");
}
}
像這裏介紹的那樣做,但核心意圖是在測試時間修改redeliveryDelay,因爲「強制」IOException不需要等待3分鐘,因此爲了加快單元測試的速度,重新傳遞延遲可以降低到像10毫秒。
爲了實現這個我的測試方法執行以下操作:
@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();
...
}
}
這裏的測試只是取代了IOException異常的onException的段首先從3分鐘降低了重新傳遞延遲到10毫秒,並增加了模擬終點。然而,當我嘗試運行單元測試,我會出現以下情況例外:
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.
然而,在official documentation的例子,據我理解正確的他們,都非常相似。我還嘗試通過已定義的ID謂詞及其相應的方法weaveById()
或通過weaveByToString()
方法查找異常定義,但沒有其他結果。我還嘗試通過weaveByType(OnExceptionDefinition.class).selectIndex(1).remove();
刪除異常定義,並通過weaveAddFirst().onException(...).async...;
添加OnException部分,但結果相同。
但是,可以通過f.e添加模擬錯誤端點。 weaveByToString("Log[io exception noticed]").after().to("mock:ioError");
因此,修改onException塊或單元測試的redeliveryDelay的任何提示都值得歡迎。
@Edit:我現在也試圖移動通過異常消息建議同時這也是在駱駝的exception samples優選情況下,路由定義(from(...)
)上面的onException的聲明。然而,在這樣做的時候,所有的測試(甚至是工作測試)在context.getRouteDefinition("someQueueID").adviceWith(context, new AdviceWithRouteBuilder() {... });
上的NullPointerException
都失敗了,因爲顯然這條路線本身已經找不到了。我懷疑這是一個IntelliJ問題,因爲這兩個類都在同一個項目中,因此路由的修改應該對測試類可見。
駱駝版本在使用中:2.13.0,IntelliJ IDEA的13.1.2
@ EDIT2:由於某些原因context.getRouteDefinitions("someQueueID")
返回NULL,如果onException的元件在from
塊之外定義,而一般路線可以通過context.getRouteDefinitions().get(0)
獲得 - 但是,該異常聲明OnException部分需要添加爲頂層元素。
另一種選擇是使redeliveryDelay(也許還有其他各種設置)的屬性,然後有一個生產性文件+測試屬性文件,具有不同的值,以滿足您的每一個需求環境。 –
@SteveHarrington雖然與注射的屬性值進入這些領域你的建議的工作,這並沒有解決與在我看來onException的塊一起爲adviceWith的核心問題。不過,如果您願意發佈答案,我願意接受您的建議作爲答案。 –