我正在为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());
这个配置运行良好,我使用BpmnAwareTest断言,所有测试都通过
<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:找不到要向ProcessEngine注册的ProcessEngine
您混淆了两个测试概念:通过spring的集成测试和通过rule的单元测试。spring-boot测试将根据您的yaml和bean配置来配置流程引擎,还将(正常(运行应用程序的大部分(数据库、消息传递等(。使用规则的单元测试在使用内存中引擎(使用内存中数据库(时效果最好。
总结:在春季启动测试中,不要使用ProcessEngineRule,使用应用程序配置的引擎。在纯流程单元测试中,不要使用spring,而是通过MockExpressionManager连接所有内容。
我发现进行单元测试的一个好方法是使用;隐藏的";引擎配置,当您只有一个引擎规则而没有其他基于spring的上下文时,总会找到它。这可以通过简单地将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 mockito和camunda bpm-assert。绝对值得研究一下,因为它使您的测试轻量级、快速、定义良好且易于阅读。
额外的好处是,测试覆盖率EngineRule将为您提供有价值的覆盖率图(html格式(,并允许基于百分比的覆盖率断言。
编辑:这是为JUnit4。你也可以用JUnit 5来做。