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

如何验证Mock服务中抽象父类方法调用并解决空指针异常?

问题根因

你当前使用Mockito.mock(MyService.class, InvocationOnMock::callRealMethod)生成的是纯Mock对象,Mock实例的所有字段默认都是null,即使指定了默认调用真实方法,Spring的@Autowired注入逻辑也不会自动触发,所以调用到userRepository的时候就会抛出空指针异常。

正确实现方案

方案1:使用Spy(部分Mock)实现(推荐)

Spy是Mockito专门为「部分方法走真实逻辑、部分方法可桩可验证」的场景设计的,默认会保留实例的原有依赖,比纯Mock加默认真实调用的方式更符合你的需求。

实现步骤:

  • 定义Mock的UserRepository实例,提前桩好查询方法的返回值
  • 构造MyService的真实实例,注入Mock的UserRepository后用Mockito.spy()包装为Spy对象
  • 调用测试方法后直接验证hello方法的调用次数

代码示例:

import org.mockito.Mock;
import org.mockito.Spy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class MyServiceTest {
    // 声明要模拟的依赖
    @Mock
    private UserRepository userRepository;
    // 声明Spy对象,默认所有方法走真实逻辑
    @Spy
    private MyService myService;

    @BeforeEach
    void init() {
        // 初始化Mock和Spy注解
        MockitoAnnotations.openMocks(this);
        // 手动把Mock的UserRepository注入到MyService中,如果你的Service有setter方法也可以直接调用setter
        ReflectionTestUtils.setField(myService, "userRepository", userRepository);
    }

    @Test
    void testWhateverShouldTriggerHello() {
        // 提前桩写UserRepository的查询返回
        User mockUser = new User();
        when(userRepository.selectById(any())).thenReturn(mockUser);

        // 构造测试入参
        MyDTO myDTO = new MyDTO();
        // 调用测试方法
        myService.whatever(myDTO);

        // 验证父类hello方法被调用1次
        verify(myService, times(1)).hello(any());
    }
}

方案2:沿用当前Mock+callRealMethod的方式

如果你不想修改现有的Mock创建逻辑,只需要手动给Mock对象的userRepository字段注入Mock的UserRepository实例即可,和方案1的注入逻辑一致:

MyService myService = Mockito.mock(MyService.class, InvocationOnMock::callRealMethod);
UserRepository mockUserRepo = mock(UserRepository.class);
// 注入依赖
ReflectionTestUtils.setField(myService, "userRepository", mockUserRepo);
// 后续桩写和调用逻辑和方案1一致
注意事项
  • 如果你的MyService使用构造器注入依赖,不需要用反射工具注入,直接new MyService(mockUserRepository)后再包装为Spy对象即可,代码更安全。
  • 不要对有Spring注入依赖的类直接使用纯Mock做真实方法调用,Spy是这类场景的最优选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:06:03