骆驼JUnit-Tests:并行执行的错误结果

时间:2018-11-22 08:02:50

标签: spring-boot junit apache-camel parallel-testing

我使用camel.version 2.18.1和spring-boot 1.5.1.RELEASE。
我有一些或多或少复杂的骆驼路线,来自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-Test,总共有将近400个JUnit-Test,它们与maven-surefire-plugin一起运行以实现并行测试执行。

<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-Tests并行运行时,这将导致生产者端点不一致( EDIT:用于测试,我使用来自Camel的Mock端点)。并行测试影响了其他测试,并且目标端点中的预期消息数不正确。

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

    ...
} 

我的问题是,是否可以并行运行Camel路由的JUnit-Tests?

我尝试在测试方法上添加@DirtiesContext,以强制Spring Testing在每种测试方法后自动重新加载CamelContext:http://camel.apache.org/testing.html
当然,哪一个在并行测试执行时不起作用,因为结果仍然是随机的,并且预期的消息数不正确。

我最终设置了这些测试,这些测试将测试到@NotThreadSafe的骆驼路由以强制执行单个线程。只能并行执行这些将测试除骆驼式路由以外的其他功能的JUnit-Test。

但这不是令人满意的解决方案,涉及近400个JUnit-Tests。
没有可以并行测试骆驼路线的任何配置或设置可以正常工作吗?

1 个答案:

答案 0 :(得分:1)

您的 MQ主题是有状态的,因此“不是线程安全的”。一旦多个测试并行运行,就无法预见主题中的消息数量

要解决此问题,您必须隔离测试的有状态部分,即MQ主题。您必须为每个测试生成唯一的MQ主题名称,以便每个测试都有其自己的MQ主题。在这种情况下,消息大小可以像在单线程执行中那样得到很好的定义。

或者作为主题内隔离的替代方法,您可以使用JMS message selectors为不同的测试隔离主题中的消息。在这种情况下,每个测试必须设置一个具有唯一值的消息头,并且仅使用具有该值的消息。