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

使用Mockito测试R2dbc Repository时实例一直为null问题求助

问题根源&解决方案

核心错误点

  • 链式打桩逻辑错误:Mockito不会自动为链式调用生成中间Mock对象,你直接对userRepository.findAll().collectList().block()打桩时,userRepository.findAll()默认返回null,调用collectList()就会直接抛出空指针,根本执行不到block方法。
  • 注解混用不兼容:@RunWith(MockitoJUnitRunner.class)是JUnit4的注解,而@BeforeEach/@AfterEach是JUnit5的注解,两者共存会导致Mock初始化失效,Repository注入为null。
  • verify使用错误:verify只能校验Mock对象的方法调用,不能校验被测试类underTest自身的方法。

正确实现代码

不需要手动Mockblock方法,直接给Reactive Repository的返回值预设真实的Publisher对象即可,原生的Publisher的block方法会正常返回对应值:

// 用JUnit5的Mockito扩展,无需手动管理Mock生命周期
@ExtendWith(MockitoExtension.class)
class UserTest {

    @InjectMocks
    private UserService underTest;
  
    @Mock
    private UserRepository userRepository;
    
    @Test
    void getApplicableUsers() {
        // 直接给findAll返回预设的Flux对象,后续collectList().block()自然返回空列表
        when(userRepository.findAll()).thenReturn(Flux.empty());

        // 若需要返回测试数据写法如下:
        // User testUser = new User();
        // when(userRepository.findAll()).thenReturn(Flux.just(testUser));
        
        Set<User> expected = underTest.getUsers(getUser(), getUsers());
        // 校验repository的findAll方法被调用一次
        verify(userRepository, times(1)).findAll();
    }
}

极端场景Mock block方法的示例(不推荐,仅作演示)

如果确实需要手动Mockblock方法,可以单独Mock中间的Flux/Mono对象:

@Mock
private Flux<User> userFlux;
@Mock
private Mono<List<User>> listMono;

// 打桩逻辑
when(userRepository.findAll()).thenReturn(userFlux);
when(userFlux.collectList()).thenReturn(listMono);
when(listMono.block()).thenReturn(new ArrayList<>());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:36:04