Как тестировать производственные маршруты в Apache Camel?

допустим, у меня есть мои маршруты, созданные в отдельном классе RouteBuilder. Это выглядит так:

  • захватить сообщение из очереди JMS
  • сделать некоторые преобразования, проверки и т. д.
  • в зависимости от результатов проверки вперед к определенной очереди JMS и сохранить что-то в DB

Я хотел бы протестировать этот маршрут без брокера JMS и без БД. Я знаю, что могу издеваться над своими реализациями процессора, но этого недостаточно. Я не хочу менять этот маршрут (предположим, я получил этот класс в файле jar). Насколько я знаю из Camel in Action (sec. 6.2.6), чтобы иметь возможность использовать насмешки конечных точек и другие вещи, мне нужно изменить определения конечных точек маршрута (в примере книги это изменение "mina:tcp://miranda" на "mock:miranda" и т. д.).

можно ли протестировать поток в полной изоляции без изменения определений маршрута? Если я получил свой RouteBuilder как отдельный класс, я вынужден каким-то образом "скопировать" определение маршрута и изменить его вручную? Разве это не проверка чего-то неправильного?

Я довольно новичок в Camel, и для меня было бы очень здорово иметь изолированный модульный тест во время deveoping маршрутов. Просто чтобы иметь возможность что-то изменить, выполните небольшой тест, наблюдать результат и так далее.

3 ответов


предполагая, что класс RouteBuilder имеет жестко закодированные конечные точки, его немного сложнее протестировать. Однако если RouteBuilder использует заполнитель свойства для uris конечной точки, то часто можно будет использовать другой набор URI конечной точки для модульных тестов. Как объясняется в главе 6 книги о верблюдах.

Если они жестко закодированы, вы можете использовать совет с функцией в модульном тесте, как показано здесь:http://camel.apache.org/advicewith.html

In Camel 2.7 мы сделали возможным манипулировать маршрутом намного проще, поэтому вы можете удалять детали, заменять детали и т. д. Вот о чем говорит линк.

например, чтобы имитировать отправку сообщения в конечную точку базы данных,вы можете использовать это выше и заменить на другое, где вы отправляете его в макет.

в предыдущих выпусках вы можете использовать трюк interceptSendToEndpoint, который также описан в книге Camel (раздел 6.3.3)


Я

   <bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
        <property name="location" value="classpath:shop.properties"/>
    </bean>

    <route>
        <from uri="direct://stock"/>
        <to uri="{{stock.out}}"/>
    </route>

в моем весеннем файле, а затем в магазине.свойства на пути тестового класса у меня есть запас.out=xxxx, который заменяется во время выполнения, поэтому я могу иметь разные маршруты один для выполнения и один для теста

theres лучший пример в 6.1.6 модульного тестирования в нескольких средах


в то время как вы можете использовать перехваты и советы для замены конечных точек в соответствии с Клаусом Ибсеном ответьте, Я думаю, что гораздо лучше позволить вашим маршрутам принять Endpoint экземпляры, чтобы тесты не были связаны с URI рабочей конечной точки.

например, скажем, у вас есть RouteBuilder что-то вроде

public class MyRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("http://someapi/someresource")
        .process(exchange -> {
            // Do stuff with exchange
        })
        .to("activemq:somequeue");
    }
}

можно вводить конечные точки вот так:

public class MyRoute extends RouteBuilder {
    private Endpoint in;
    private Endpoint out;

    // This is the constructor your production code can call
    public MyRoute(CamelContext context) {
        this.in = context.getEndpoint("http://someapi/someresource");
        this.out = context.getEndpoint("activemq:somequeue");
    }

    // This is the constructor your test can call, although it would be fine
    // to use in production too
    public MyRoute(Endpoint in, Endpoint out) {
        this.in = in;
        this.out = out;
    }

    @Override
    public void configure() throws Exception {
        from(this.in)
        .process(exchange -> {
            // Do stuff with exchange
        })
        .to(this.out);
    }
}

который затем может быть протестирован как это:

public class MyRouteTest {
    private Endpoint in;
    private MockEndpoint out;
    private ProducerTemplate producer;

    @Before
    public void setup() {
        CamelContext context = new DefaultCamelContext();

        this.in = context.getEndpoint("direct:in");
        this.out = context.getEndpoint("mock:direct:out", MockEndpoint.class);
        this.producer = context.createProducerTemplate();
        this.producer.setDefaultEndpoint(this.in);

        RouteBuilder myRoute = new MyRoute(this.in, this.out);
        context.addRoutes(myRoute);

        context.start();
    }

    @Test
    public void test() throws Exception {
        this.producer.sendBody("Hello, world!");
        this.out.expectedMessageCount(1);
        this.out.assertIsSatisfied();
    }
} 

это имеет следующие преимущества:

  • ваш тест очень прост и легко понять, и даже не нужно продлить CamelTestSupport или другие вспомогательные классы
  • the CamelContext создается вручную, поэтому вы можете быть уверены, что создается только тестируемый маршрут
  • тест не заботится о производственном маршруте URIs
  • у вас все еще есть удобство жесткого кодирования URI конечной точки в класс маршрута если вы хотите