如何编写Camunda流程的Spring Boot集成测试并解决Mock失效问题?
Camunda流程Spring Boot集成测试优化方案
问题核心
你当前通过MockMvc调用接口启动Camunda流程,用@MockBean模拟依赖服务,但测试结果不稳定——Mock方法有时被调用、有时不被调用。本质原因大多是Camunda流程的异步执行特性,导致测试线程跑完断言时,流程任务还没执行到Mock方法;或是上下文加载问题,MockBean没有正确替换流程委托类中的依赖实例。
优化实现方案
1. 强制流程同步执行(最快解决异步问题)
Camunda默认会用异步执行器处理任务,导致流程和测试线程不同步。直接在测试配置中关闭异步执行,让流程任务在测试线程里同步完成:
@RunWith(SpringRunner.class) @SpringBootTest(properties = { "camunda.bpm.job-execution.enabled=false", "camunda.bpm.async-execution.enabled=false" }) @AutoConfigureMockMvc public class CamundaIT { // 保留你原有的测试代码即可 }
2. 直接用Camunda引擎API测试(最可靠的流程测试方式)
跳过Controller层,直接调用Camunda的RuntimeService启动流程,聚焦流程逻辑本身,避免HTTP请求带来的异步干扰:
@RunWith(SpringRunner.class) @SpringBootTest public class CamundaProcessTest { @Autowired private RuntimeService runtimeService; @MockBean private ProcessService processService; @MockBean private ProcessServiceTwo processServiceTwo; @Test public void testFullProcessFlow() { // 配置Mock返回值 when(processService.doTask(anyString())).thenReturn("MockedResponse"); when(processServiceTwo.doAnotherTask(anyString())).thenReturn("Success"); // 直接启动流程(替换成你的流程定义Key) ProcessInstance processInstance = runtimeService.startProcessInstanceByKey( "your-process-key", Collections.singletonMap("input", "test-input-value") ); // 验证流程是否正常结束 assertThat(processInstance.isEnded()).isTrue(); // 验证Mock方法确实被调用 verify(processService).doTask("test-input-value"); verify(processServiceTwo).doAnotherTask(anyString()); } }
3. 保留Controller层时的稳定测试方案
如果必须通过接口启动流程,需要在测试中等待流程执行完成后再做断言:
@Test public void testCamundaProcess() throws Exception { // 配置Mock when(processService.doTask(anyString())).thenReturn(TestHelper.getResponse()); when(processServiceTwo.doAnotherTask(anyString())).thenReturn("Success"); // 调用接口启动流程 mvc.perform(post("/process/initiate") .contentType(MediaType.APPLICATION_JSON) .content(mapper.writeValueAsString(request)) .andExpect(status().isOk()); // 轮询等待流程结束(比固定sleep更可靠) long timeout = System.currentTimeMillis() + 10000; // 10秒超时 while (System.currentTimeMillis() < timeout) { ProcessInstance instance = runtimeService.createProcessInstanceQuery() .processInstanceBusinessKey(request.getBizKey()) // 用请求中的业务键定位流程 .singleResult(); if (instance == null || instance.isEnded()) { break; } Thread.sleep(500); } // 验证Mock调用 verify(processService).doTask(anyString()); verify(processServiceTwo).doAnotherTask(anyString()); }
4. 检查MockBean的有效性
确保你的@MockBean确实替换了流程委托类中的依赖:
- 确认
ProcessService是单例Bean,且ProcessTaskDelegate中注入的是同一个实例 - 不要在
@Before方法中重复初始化Mock相关对象,避免上下文冲突
内容的提问来源于stack exchange,提问作者thecheesegrater
相关产品推荐
相关产品推荐

