You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:45:03