Teste de rota de camelo usando conselhosCom definições de OnException

Eu tenho uma definição de rota Camel muito simples, que inclui apenas alguns predicados OnException para lidar com as respectivas exceções e algumas instruções de log.

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

O bean em si também é simples, apenas verifica um parâmetro de cabeçalho e lança uma exceção apropriada

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 essa configuração de teste é apenas uma pequena parte de um projeto maior, pode parecer bobagem fazê-lo como apresentado aqui, mas o principal objetivo é modificar o redeliveryDelay no tempo de teste, pois uma IOException "forçada" não precisará esperar 3 minutos portanto, para acelerar um pouco os testes de unidade, o atraso na entrega pode ser reduzido para 10 ms.

Para conseguir isso, meu método de teste faz o seguinte:

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

Aqui, o teste substitui o segmento onException do IOException para reduzir primeiro o atraso da entrega de 3 minutos para 10 ms e adicionar um ponto final simulado no final. No entanto, quando tento executar o teste de unidade, receberei a seguinte exceção:

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.

No entanto, os exemplos nodocumentação oficial, tanto quanto eu os entendi corretamente, são muito semelhantes. Também tentei procurar a definição de exceção por meio de um predicado de ID definido e seu método correspondenteweaveById() ou através doweaveByToString() método, mas sem nenhum outro resultado. Eu também tentei remover a definição de exceção viaweaveByType(OnExceptionDefinition.class).selectIndex(1).remove(); e adicione a parte OnException viaweaveAddFirst().onException(...).async...; mas com o mesmo resultado.

Anexar um ponto de extremidade de erro simulado, no entanto, é possível via f.e.weaveByToString("Log[io exception noticed]").after().to("mock:ioError");

Portanto, qualquer dica para modificar blocos onException ou redeliveryDelay para testes de unidade é bem-vinda.

@ Edit: Eu também tentei agora mover as declarações onException acima da definição de rota (from(...)), como sugerido pela mensagem de exceção, e esse também foi o caso preferido no Camel'samostras de exceção. Ao fazer isso, no entanto, todos os testes (mesmo os que estão funcionando) falham a partir de umNullPointerException emcontext.getRouteDefinition("someQueueID").adviceWith(context, new AdviceWithRouteBuilder() {... }); como obviamente a rota em si não pode mais ser encontrada. Duvido que esse seja um problema do IntelliJ, pois as duas classes estão dentro do mesmo projeto e, portanto, uma modificação da rota deve ser visível para a classe de teste.

Versão camel em uso: 2.13.0, IntelliJ IDEA 13.1.2

@ Edit2: Por alguma razãocontext.getRouteDefinitions("someQueueID") retorna null se os elementos OnException forem definidos fora dofrom bloco, enquanto a rota geral pode ser obtida viacontext.getRouteDefinitions().get(0) - no entanto, a exceção informando que a parte OnException precisa ser adicionada como elemento de nível superior permanece.

questionAnswers(1)

yourAnswerToTheQuestion