Ich habe eine sehr einfache Camel Route Definition, die nur einige OnException Prädikate enthält, um entsprechende Ausnahmen und einige Protokollanweisungen zu behandeln.Camel route-testing mit adviceWith mit OnException Definitionen
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");
Die Bohne selbst zu einfach ist, überprüft er nur einen Header-Parameter und löst eine entsprechende Ausnahme
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");
}
}
Da dieser Test-Setup nur ein kleiner Teil eines größeren Projekts ist es albern klingt Dies ist wie hier dargestellt, aber der Kern besteht darin, die RedeliveryDelay zum Testzeitpunkt zu ändern, da eine "erzwungene" IOException nicht 3 Minuten warten muss. Daher kann die Neuzustellungsverzögerung reduziert werden, um Unit Tests ein wenig zu beschleunigen wie 10 ms.
Um diese meinen Test-Methode zu erreichen, führt Folgendes aus:
@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();
...
}
}
Hier der Test ersetzt nur das OnException Segment der IOException zuerst die Nachlieferung Verzögerung von 3 Minuten bis 10 ms zu reduzieren und fügt eine Schein-Endpunkt am Ende. Allerdings, wenn ich versuchen, das Gerät zu testen laufen werde ich die folgende Ausnahme erhalten:
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.
Allerdings sind die Beispiele in der official documentation, soweit ich verstanden sie richtig, sind sehr ähnlich. Ich habe auch versucht, die Ausnahmedefinition über ein definiertes ID-Prädikat und seine entsprechende Methode weaveById()
oder über die weaveByToString()
-Methode nachzuschlagen, aber mit keinem anderen Ergebnis. Ich habe auch versucht, die Ausnahmedefinition über weaveByType(OnExceptionDefinition.class).selectIndex(1).remove();
zu entfernen und den OnException-Teil über weaveAddFirst().onException(...).async...;
hinzuzufügen, aber mit dem gleichen Ergebnis.
Das Anfügen eines verspotteten Fehlerendpunkts ist jedoch über z.B. weaveByToString("Log[io exception noticed]").after().to("mock:ioError");
Also alle Tipps zum Ändern onException Blöcke oder die RedeliveryDelay für Komponententests sind mehr als willkommen.
@Edit: Ich nun auch versucht, die OnException Erklärungen über der Routendefinition zu bewegen (from(...)
), wie durch die Ausnahmemeldung vorgeschlagen und dies war auch der bevorzugte Fall in Camel exception samples. Dabei versagen jedoch alle Tests (auch die Working-Tests) ab NullPointerException
unter context.getRouteDefinition("someQueueID").adviceWith(context, new AdviceWithRouteBuilder() {... });
, da offensichtlich die Route selbst nicht mehr gefunden werden kann. Ich bezweifle, dass dies ein IntelliJ-Problem ist, da beide Klassen innerhalb des gleichen Projekts liegen und daher eine Änderung der Route für die Testklasse sichtbar sein sollte.
Camel-Version im Einsatz: 2.13.0, IntelliJ IDEA 13.1.2
@ Edit2: Aus irgendeinem Grund context.getRouteDefinitions("someQueueID")
NULL, wenn die OnException Elemente außerhalb des from
Block definiert, während die allgemeine Route kann über context.getRouteDefinitions().get(0)
abgerufen werden - obwohl die Ausnahme, die besagt, dass der OnException-Teil als Element auf oberster Ebene hinzugefügt werden muss, bleibt.
Eine weitere Option ist die redeliveryDelay (und vielleicht auch verschiedene andere Einstellungen), um eine Eigenschaft zu machen, und dann eine Produktionseigenschaften Datei + ein Test Properties-Datei, mit differierende Werte Ihren Bedürfnissen in jeder passen Umgebung. –
@SteveHarrington Obwohl Ihr Vorschlag beim Eingeben von Eigenschaftswerten in diese Felder funktioniert, löst dies meines Erachtens nicht das Kernproblem für Ratschläge in Verbindung mit OnException-Blöcken. Ich möchte jedoch Ihren Vorschlag als Antwort akzeptieren, wenn Sie bereit sind, eine Antwort zu veröffentlichen. –