1

我正在为 Camunda 工作流程编写测试用例。我正在使用 SpringRunner@RunWith(SpringRunner.class)并在测试执行所需的测试类中具有以下属性

        @Autowired
        private ProcessEngine processEngine;
    
        @Rule
        @ClassRule
        public static ProcessEngineRule rule;
    
        @PostConstruct
        void initRule() {
            rule = TestCoverageProcessEngineRuleBuilder.create(processEngine).withDetailedCoverageLogging().build();
        }
        @Mock
        ProcessScenario someProcessScenario;

此外,在每个测试中,我都会像这样实例化 ProcessInstance

ProcessRunner.ExecutableRunner.StartingByStarter starter = Scenario.run(someProcessScenario)
            .startBy(() -> {
                processInstance = rule.getRuntimeService().startProcessInstanceByKey("PROCESS_DEFINITION", properties);
                return processInstance;
            });

starter.engine(rule.getProcessEngine());

此配置工作正常,我使用 BpmnAwareTests 断言并且所有测试都通过了。我在 pom 中使用的依赖项是

<dependency>
        <groupId>org.camunda.bpm.assert</groupId>
        <artifactId>camunda-bpm-assert</artifactId>
        <version>5.0.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.camunda.bpm.extension</groupId>
        <artifactId>camunda-bpm-assert-scenario</artifactId>
        <version>1.1.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.camunda.bpm.extension</groupId>
        <artifactId>camunda-bpm-process-test-coverage</artifactId>
        <version>0.3.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.camunda.bpm.extension.mockito</groupId>
        <artifactId>camunda-bpm-mockito</artifactId>
        <scope>test</scope>
        <version>4.12.0</version>
    </dependency>

由于这个设置为每个测试类实例化了 spring 容器,我想改变几个类来运行 MockitoJUnitRunner 而不是 SpringRunner。所以我把那些改成@RunWith(MockitoJUnitRunner.class)

并像这样初始化所需的属性:

@Rule
public ProcessEngineRule rule = new ProcessEngineRule();

@Mock
ApplicationEventPublisher eventPublisher;

@Mock
ProcessScenario someOtherProcess;

@Mock
SomeClass someclass;


@Before
public void setUp() throws MyCustomiException {
    MockitoAnnotations.openMocks(this);
    MyDelegate myDelegate = new MyDelegate(someclass);
    Mocks.register("myDelegate", myDelegate);
    ......
}

ProcessInstance 在上面的所有测试用例中都被实例化。这些测试也可以顺利运行并独立通过。但是,当我运行所有测试(一些使用 SpringRunner 和其他使用 MockitoJUnitRunner 运行)时,它们没有通过。SpringRunner 的所有测试都失败了,在 SpringRunner 之后执行的测试也失败了。错误是java.lang.IllegalStateException: No ProcessEngine found to be registered with ProcessEngines!

4

2 回答 2

0

我发现进行单元测试的一个好方法是使用“隐藏的”引擎配置,当您只有一个引擎规则而没有其他基于弹簧的上下文时,它总是会被寻找。这可以通过简单地将 camunda.cfg.xml 添加到您的测试资源来完成,如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.camunda.bpm.extension.process_test_coverage.junit.rules.ProcessCoverageInMemProcessEngineConfiguration">

    <property name="jdbcUrl" value="jdbc:h2:mem:camunda;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

    <!-- Database configurations -->
    <property name="databaseSchemaUpdate" value="true" />

    <!-- job executor configurations -->
    <property name="jobExecutorActivate" value="false" />

    <property name="history" value="full" />    
  </bean>
</beans>

请注意,这使用了流程覆盖引擎配置,您可以在此处查找。但是您可以使用任何其他配置。

一旦你有了这个引擎配置,你就可以像这样简单地创建一个单元测试:

@Deployment(resources = "myBpmFile.bpmn")
public class ApplicationTest {

    private static final String PROCESS_DEFINITION_KEY = "myProcessDefinitionKey";

    @Rule
    @ClassRule
    public static ProcessEngineRule rule = TestCoverageProcessEngineRuleBuilder.create().build();

    private RuntimeService runtimeService;

    @Before
    public void setup() {
        runtimeService = rule.getRuntimeService();

        registerJavaDelegateMock(MyDelegate.class)
        //register more mocks
    }

    @Test
    public void testHappyPath() {
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINITION_KEY);
        assertThat(processInstance).isActive();

        assertThat(processInstance).hasPassed("MyServiceTask");
        verifyJavaDelegateMock(MyDelegate.class).executed();

        assertThat(processInstance).isWaitingAtExactly("MyUserTask");
        complete(task());

        assertThat(processInstance).isEnded();
    }
}

请注意,这使用camunda-bpm-mockitocamunda-bpm-assert。绝对值得研究一下,因为它使您的测试轻量级、快速、定义明确且易于阅读。

作为额外的奖励,测试覆盖引擎规则将为您提供有价值的覆盖图(html 格式)并允许基于百分比的覆盖断言。

编辑:这是针对 JUnit4 的。您也可以使用 JUnit 5 来​​实现。

于 2021-12-22T19:27:19.313 回答
0

您混淆了两个测试概念:通过 spring 的集成测试和通过规则的单元测试。spring boot 测试将根据您的 yaml 和 bean 配置配置流程引擎,并且(通常)运行大部分应用程序(数据库、消息传递......)。使用该规则的单元测试在使用内存引擎(使用内存数据库)时效果最佳。

总结:在你的spring boot测试中,不要使用ProcessEngineRule,使用你的app配置的引擎。在您的纯流程单元测试中,不要使用弹簧,通过 MockExpressionManager 连接所有内容。

于 2021-12-16T23:28:45.247 回答