Mockito测试Criteria multiselect查询单元测试出现NullPointerException问题
问题原因排查
你遇到的空指针和where方法未调用的问题,核心是Mock对象的方法返回值缺失,执行到in查询构造行时链式调用过程中出现null值,代码提前抛出异常,自然无法执行到后续的where方法调用。具体缺失的Mock逻辑如下:
- 所有
Root实例的get(字段名)方法没有配置Mock返回值,默认返回null CriteriaBuilder的in()方法返回的In实例没有Mock,且In.value()链式调用需要返回自身- 部分链式调用方法(如
query.where、query.distinct、getResultList)没有配置返回值
修复方案
第一步:修正Mock对象的泛型匹配
将测试类中不匹配的泛型修正:
// 原写法错误,和业务代码的Object[]不匹配 // @Mock // CriteriaQuery<Object> query; // @Mock // Query<Object> result; // 修正后 @Mock CriteriaQuery<Object[]> query; @Mock Query<Object[]> result;
第二步:补充缺失的Mock声明
新增需要用到的Mock实例:
@Mock Path<String> bTypePath; @Mock Path<Object> bFieldIdPath, cFieldIdPath, aTypePath, aFieldIdPath, aNamePath, aAveragePath; @Mock In<String> inPredicate; @Mock Predicate equalPredicate;
第三步:测试方法中补充Mock逻辑
在dao.findAll()执行前补充如下返回配置:
// 配置所有Root.get()方法的返回值 Mockito.when(mockBRoot.get("fieldId")).thenReturn(bFieldIdPath); Mockito.when(mockCRoot.get("fieldId")).thenReturn(cFieldIdPath); Mockito.when(mockBRoot.get("type")).thenReturn(bTypePath); Mockito.when(mockARoot.get("type")).thenReturn(aTypePath); Mockito.when(mockARoot.get("fieldId")).thenReturn(aFieldIdPath); Mockito.when(mockARoot.get("name")).thenReturn(aNamePath); Mockito.when(mockARoot.get("average")).thenReturn(aAveragePath); // 配置CriteriaBuilder的谓词构造方法返回 Mockito.when(criteriaBuilder.equal(Mockito.any(), Mockito.any())).thenReturn(equalPredicate); Mockito.when(criteriaBuilder.in(bTypePath)).thenReturn(inPredicate); // 配置In.value的链式调用返回自身 Mockito.when(inPredicate.value(Mockito.anyString())).thenReturn(inPredicate); // 配置CriteriaQuery链式调用的返回 Mockito.when(query.multiselect(Mockito.any(Selection[].class))).thenReturn(query); Mockito.when(query.where(Mockito.any(Predicate[].class))).thenReturn(query); Mockito.when(query.distinct(Mockito.anyBoolean())).thenReturn(query); // 配置最终查询结果返回 Mockito.when(result.getResultList()).thenReturn(Collections.emptyList());
补充说明
如果需要验证查询逻辑的正确性,建议额外编写集成测试,使用H2等内存数据库执行真实查询,单元测试仅用于验证DAO层的方法调用流程即可。
内容的提问来源于stack exchange,提问作者Rocco
相关产品推荐
相关产品推荐

