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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 13:39:03