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

如何测试基于CriteriaBuilder和CriteriaQuery构建的查询?

测试依赖JPA Criteria API业务方法的解决方案

问题根因

直接mock EntityManager时默认返回null属性,直接打桩查询返回结果会跳过Criteria构造逻辑的校验,无法验证查询条件拼接的正确性。

推荐测试方案(覆盖单元测试、集成测试两种场景)

方案1:单元测试场景(仅校验Criteria构造逻辑,无需连接数据库)

  • 第一步:显式mock业务代码中用到的所有Criteria相关核心对象,不要依赖mock框架的默认返回值
    按调用顺序依次打桩依赖对象,示例(基于Mockito):
    // 初始化所有核心mock对象
    EntityManager entityManager = Mockito.mock(EntityManager.class);
    CriteriaBuilder criteriaBuilder = Mockito.mock(CriteriaBuilder.class);
    CriteriaQuery<User> criteriaQuery = Mockito.mock(CriteriaQuery.class);
    Root<User> root = Mockito.mock(Root.class);
    Predicate agePredicate = Mockito.mock(Predicate.class);
    
    // 按业务代码的调用顺序绑定返回值
    when(entityManager.getCriteriaBuilder()).thenReturn(criteriaBuilder);
    when(criteriaBuilder.createQuery(User.class)).thenReturn(criteriaQuery);
    when(criteriaQuery.from(User.class)).thenReturn(root);
    when(criteriaBuilder.greaterThan(root.get("age"), 18)).thenReturn(agePredicate);
    
  • 第二步:调用业务方法后,通过mock校验验证Criteria逻辑正确性
    不需要真的执行查询,只需校验Criteria API的调用参数、顺序是否符合预期,即可验证查询拼接逻辑:
    // 调用待测试的业务方法
    List<User> result = userService.queryAdultUsers("张三");
    
    // 校验Criteria构造逻辑符合预期
    verify(criteriaBuilder).greaterThan(root.get("age"), 18);
    verify(criteriaBuilder).equal(root.get("name"), "张三");
    verify(criteriaQuery).where(any(Predicate[].class));
    verify(entityManager).createQuery(criteriaQuery);
    

方案2:集成测试场景(同时验证查询逻辑和执行结果)

  • 引入H2内存数据库作为测试数据源,配置测试用JPA上下文,让容器自动注入真实的EntityManager实例,无需mock
  • 测试前向H2插入预置测试数据,调用业务方法后比对返回结果和预期值,既可以验证Criteria构造逻辑,也可以验证查询实际执行效果
  • SpringBoot场景配置示例(application-test.yml):
    spring:
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
        username: sa
        password:
      jpa:
        hibernate:
          ddl-auto: create-drop
        show-sql: true
    

避坑说明

  • 不要直接对entityManager.createQuery(criteriaQuery).getResultList()打桩固定返回值,这种写法会跳过所有Criteria构造逻辑的校验,测试完全失去意义
  • 单元测试场景下要严格匹配业务代码中Criteria API的调用顺序打桩,否则会出现空指针异常
  • 集成测试场景下H2数据库会在测试结束后自动销毁,不需要手动清理测试数据

内容的提问来源于stack exchange,提问作者stackunderflow123

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:12:02