如何在JPA+Mockito环境下Mock QueryDSL中的join关联查询逻辑
问题解答
结论
完全可以通过Mockito实现这类QueryDSL关联查询逻辑的Mock。
报错原因
你遇到的空指针异常是由QueryDSL的流式调用特性导致的:JPAQuery的leftJoin、on、where等方法都属于链式调用方法,每一步执行完成后都需要返回当前JPAQuery实例本身才能支持后续链式调用。你当前只Mock了selectFrom返回queryMock,但没有配置leftJoin等方法的返回值,Mockito默认会返回null,调用null的on()方法就触发了空指针。
最优解决方案
使用Mockito内置的RETURNS_SELFAnswer创建queryMock,该Answer会自动让所有流式Builder风格的方法返回Mock对象本身,无需逐个配置每个链式方法的返回值。
完整修正后的测试代码
@Mock private JPAQueryFactory queryFactory; @InjectMocks private BlahRepository blahRepository; @Test void byId() { // arrange // 使用RETURNS_SELF创建Mock,自动适配流式调用返回自身 JPAQuery<YyzPerEntity> queryMock = mock(JPAQuery.class, Mockito.RETURNS_SELF); when(queryFactory.selectFrom(QYyzPerEntity.yzPerEntity)) .thenReturn(queryMock); // 构造真实的返回实体,不要返回Q类实例 YyzPerEntity mockEntity = new YyzPerEntity(); // 可按需给mockEntity设置属性 when(queryMock.fetch()).thenReturn(List.of(mockEntity)); // act List<YyzPerEntity> yyzPerById = blahRepository.getYyzPerById(123L); // assert assertThat(yyzPerById).isNotNull(); // 可扩展更多断言逻辑 }
可选方案(不使用RETURNS_SELF的手动配置)
如果你需要对join、where等方法的调用做参数校验,也可以手动逐个配置链式方法的返回值,示例如下:
JPAQuery<YyzPerEntity> queryMock = mock(JPAQuery.class); when(queryFactory.selectFrom(QYyzPerEntity.yzPerEntity)).thenReturn(queryMock); when(queryMock.leftJoin(any(EntityPath.class))).thenReturn(queryMock); when(queryMock.on(any(Predicate.class))).thenReturn(queryMock); when(queryMock.where(any(Predicate.class))).thenReturn(queryMock); // 后续配置fetch返回值即可
注意事项
不要在fetch的返回值中返回QueryDSL的Q类实例,Q类是元模型对象不是业务实体,会触发类型转换异常,需要构造真实的YyzPerEntity业务实体作为返回结果。
内容的提问来源于stack exchange,提问作者DerBenniAusA
相关产品推荐
相关产品推荐

