Как протестировать производственные маршруты в Apache Camel? - PullRequest
19 голосов
/ 14 апреля 2011

Допустим, мои маршруты созданы в отдельном классе RouteBuilder. Похоже:

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

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

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

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

Ответы [ 3 ]

24 голосов
/ 14 апреля 2011

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

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

В Camel 2.7 мы упростили управление маршрутом, поэтому вы можете удалять детали, заменять детали и т. Д. Об этом говорит ткацкий материал, о котором говорит ссылка.

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

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

О, вы также можете заменить компоненты на фиктивный компонент, как показано на странице 169. Теперь в Camel 2.8 и далее, фиктивный компонент больше не будет жаловаться на параметры uri, которые он не знает. Это означает, что гораздо проще заменить компоненты на макеты на уровне компонентов.

4 голосов
/ 14 апреля 2011

у меня

   <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>

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

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

0 голосов
/ 15 сентября 2017

В то время как вы можете использовать перехваты и советы, чтобы поменять конечные точки в соответствии с Клаусом Ибсеном ответьте, я думаю, что гораздо лучше разрешить вашим маршрутам принимать 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 или другие вспомогательные классы
  • CamelContext создается вручную, поэтому вы можете быть уверены, что создается только тестируемый маршрут
  • тест не заботится об идентификаторах URI производственного маршрута
  • у вас все еще есть удобство жесткого кодирования URI конечной точки в классе маршрута, если вы хотите
...