Camel JUnit-Tests: неверные результаты при параллельном выполнении
Я использую camel.version 2.18.1 и spring-boot 1.5.1.RELEASE.
У меня есть несколько более или менее сложных маршрутов Camel, где сообщения из тем MQ будут потребляться, фильтроваться, преобразовываться и, наконец, маршрутизироваться в разные темы MQ.
from("{{sourceEP}}").to("{{archiveEP}}")
.process(new MyProcessor())
.to("{{archiveEP}}").to("{{resultEP}}");
application.properties
sourceEP=jms:topic:SOURCE
archiveEP=jms:topic:ARCHIVE
resultEP=jms:topic:TARGET
Для каждого маршрута существует более 40 различных сценариев. Поэтому у меня есть около 50 JUnit-тестов для каждого маршрута, в общей сложности у меня есть около 400 JUnit-тестов, которые я запускаю с подключаемым модулем maven-surefire для достижения параллельного выполнения тестов.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<parallel>classes</parallel>
<threadCount>4</threadCount>
</configuration>
</plugin>
Проблема в том, что когда JUnit-тесты выполняются параллельно, это приведет к несогласованности в конечных точках производителя (EDIT: для тестирования я использую конечные точки Mock от Camel). Параллельные тесты повлияли на другие тесты, и ожидаемое количество сообщений в целевых конечных точках неверно.
Тест: application.properties
sourceEP=direct:start
archiveEP=mock:archive
resultEP=mock:result
RouteTest.java
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = MyApplication.class)
public class RouteTest {
@Autowired
private CamelContext context;
@EndpointInject(uri = "{{archiveEP}}")
protected MockEndpoint archiveEndpoint;
@EndpointInject(uri = "{{resultEP}}")
protected MockEndpoint resultEndpoint;
@Produce(uri = "{{sourceEP}}")
protected ProducerTemplate sourceEndpoint;
@Before
public void setup() {
sourceEndpoint.cleanUp();
archiveEndpoint.reset();
resultEndpoint.reset();
}
@Test
public void test1() throws Exception {
sourceEndpoint.sendBody("some text");
archiveEndpoint.expectedMessageCount(2);
archiveEndpoint.assertIsSatisfied();
resultEndpoint.expectedMessageCount(1);
resultEndpoint.assertIsSatisfied();
resultEndpoint.expectedBodiesReceived("expected output");
}
@Test
public void test2() throws Exception {
sourceEndpoint.sendBody("another text");
archiveEndpoint.expectedMessageCount(2);
archiveEndpoint.assertIsSatisfied();
resultEndpoint.expectedMessageCount(1);
resultEndpoint.assertIsSatisfied();
resultEndpoint.expectedBodiesReceived("another output");
}
...
}
Мой вопрос, возможно ли вообще запускать маршруты JUnit-Tests of Camel параллельно?
Я пытался добавить @DirtiesContext
о методах тестирования, чтобы заставить Spring Testing автоматически перезагружать CamelContext после каждого метода тестирования: http://camel.apache.org/testing.html
Что, конечно, не работает при параллельном выполнении теста, потому что результат все еще случайный и ожидаемое количество сообщений неверно.
Я закончил, чтобы установить эти тесты, которые будут проверять маршруты Camel в @NotThreadSafe
для обеспечения выполнения одного потока. Только эти JUnit-тесты, которые будут тестировать другие функциональные возможности, кроме маршрутизации Camel, выполняются параллельно.
Но это не является удовлетворительным решением относительно суммы около 400 JUnit-тестов.
Нет ли какой-либо конфигурации или настройки для параллельного тестирования маршрутов Camel, которые будут работать правильно?
1 ответ
Ваши MQ темы с состоянием и, следовательно, "не потокобезопасны". Как только несколько тестов выполняются параллельно, количество сообщений в темах не предвидится.
Чтобы решить эту проблему, вы должны изолировать часть ваших тестов с сохранением состояния, то есть темы MQ. Вам нужно будет генерировать уникальные имена тем MQ для каждого теста, чтобы у каждого теста были свои собственные темы MQ. В этом случае размер сообщения четко определяется как при однопоточном выполнении.
В качестве альтернативы изоляции в теме можно использовать селекторы сообщений JMS, чтобы изолировать сообщения в теме для различных тестов. В этом случае каждый тест должен установить заголовок сообщения с уникальным значением и использовать только сообщения с этим значением.