Prueba de ruta en camello con consejos Con definiciones OnException

Tengo una definición de ruta Camel muy simple que solo incluye algunos predicados OnException para manejar las excepciones respectivas y algunas declaraciones de registro.

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");

El bean en sí también es simple, solo verifica un parámetro de encabezado y genera una excepción apropiada

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");
    }
}

Como esta configuración de prueba es solo una pequeña parte de un proyecto más grande, puede parecer una tontería hacerlo como se presenta aquí, pero la intención principal es modificar el RetraiveryDelay en el momento de la prueba ya que una IOException "forzada" no tendrá que esperar 3 minutos y, por lo tanto, para acelerar un poco las pruebas unitarias, la demora de reenvío podría reducirse a unos 10 ms.

Para lograr esto, mi método de prueba hace lo siguiente:

@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();
        ...
    }
}

Aquí, la prueba simplemente reemplaza el segmento onException de IOException para reducir primero el retraso de reenvío de 3 minutos a 10 ms y agrega un punto final falso al final. Sin embargo, cuando trato de ejecutar la prueba unitaria, obtendré la siguiente excepción:

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.

Sin embargo, los ejemplos en eldocumentación oficial, por lo que entendí correctamente, son muy similares. También intenté buscar la definición de excepción a través de un predicado de ID definido y su método correspondienteweaveById() o a través deweaveByToString() método pero sin otro resultado. También intenté eliminar la definición de excepción a través deweaveByType(OnExceptionDefinition.class).selectIndex(1).remove(); y agregue la parte OnException a través deweaveAddFirst().onException(...).async...; pero con el mismo resultado.

Sin embargo, es posible agregar un punto final de error simulado a través de f.e.weaveByToString("Log[io exception noticed]").after().to("mock:ioError");

Por lo tanto, cualquier sugerencia para modificar los bloques onException o el RedeliveryDelay para las pruebas unitarias son más que bienvenidos.

@Edit: también intenté mover las declaraciones onException por encima de la definición de ruta (from(...)) como lo sugiere el mensaje de excepción y este también fue el caso preferido en Camel'smuestras de excepción. Sin embargo, al hacer esto, todas las pruebas (incluso las que funcionan) fallan a partir deNullPointerException encontext.getRouteDefinition("someQueueID").adviceWith(context, new AdviceWithRouteBuilder() {... }); obviamente, la ruta en sí ya no se puede encontrar. Dudo que este sea un problema de IntelliJ ya que ambas clases están dentro del mismo proyecto y, por lo tanto, una modificación de la ruta debería ser visible para la clase de prueba.

Versión en camello en uso: 2.13.0, IntelliJ IDEA 13.1.2

@ Edit2: por alguna razóncontext.getRouteDefinitions("someQueueID") devuelve nulo si los elementos OnException se definen fuera defrom bloque, mientras que la ruta general se puede obtener a través decontext.getRouteDefinitions().get(0) - Sin embargo, la excepción que indica que la parte OnException debe agregarse como elemento de nivel superior permanece.

Respuestas a la pregunta(1)

Su respuesta a la pregunta