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

如何实现多层Mock对象注入?解决UserSshKeyService空指针异常

多层依赖的Mock注入问题解决方法

场景代码

UserSshKeyService实现

@Service
public class UserSshKeyService {

    private final RecordEventService eventService;
    private final UserSshKeyRepository repository;

    public UserSshKeyService(RecordEventService eventService,
                          UserSshKeyRepository repository){}

}

RecordEventService实现

@Service
public class RecordEventService {

    private final UserSshKeyEventLogRepository repository;

    // 注意:原始代码此处构造方法类名写错,需修正为RecordEventService
    public RecordEventService(UserSshKeyEventLogRepository repository){}

}

尝试的测试写法

写法一

@InjectMocks
private UserSshKeyService userSshKeyService;
@InjectMocks
private RecordEventService eventService;
@Mock
UserSshKeyRepository userSshKeyRepository;
@Mock
UserSshKeyEventLogRepository userSshKeyEventLogRepository;

写法二

@InjectMocks
private UserSshKeyService userSshKeyService;
@Spy
@InjectMocks
private RecordEventService eventService;
@Mock
UserSshKeyRepository userSshKeyRepository;
@Mock
UserSshKeyEventLogRepository userSshKeyEventLogRepository;

遇到的问题

执行测试时,UserSshKeyService中的eventService抛出空指针异常,无法完成多层对象的Mock注入。


解决方法

核心问题说明

@InjectMocks的逻辑很明确:只把测试类中标记为@Mock/@Spy的对象,注入到被@InjectMocks标记的目标对象里。你之前的写法里,userSshKeyService和eventService都是被注入的目标,Mockito不会把一个注入目标当成另一个的依赖源,所以userSshKeyService里的eventService自然是空的。

正确实现方式

方案一:用@Mock完全模拟RecordEventService

如果不需要RecordEventService的真实逻辑,直接把它标记为@Mock,让Mockito自动注入到上层的UserSshKeyService中:

// 测试类需加注解:JUnit4用@RunWith(MockitoJUnitRunner.class),JUnit5用@ExtendWith(MockitoExtension.class)
@InjectMocks
private UserSshKeyService userSshKeyService;

@Mock
private RecordEventService eventService;
@Mock
private UserSshKeyRepository userSshKeyRepository;
@Mock
private UserSshKeyEventLogRepository userSshKeyEventLogRepository;

方案二:用@Spy保留RecordEventService的真实逻辑

如果需要RecordEventService执行真实代码,就用@Spy标记,同时确保它的依赖被正确注入:

@InjectMocks
private UserSshKeyService userSshKeyService;

@Spy
private RecordEventService eventService;

@Mock
private UserSshKeyRepository userSshKeyRepository;
@Mock
private UserSshKeyEventLogRepository userSshKeyEventLogRepository;

@Before
public void setUp() {
    // 初始化Mockito注解,确保依赖注入生效
    MockitoAnnotations.openMocks(this);
    // 也可以手动构造Spy对象,避免依赖自动注入可能的问题
    // eventService = new RecordEventService(userSshKeyEventLogRepository);
}

额外注意事项

  • 修正RecordEventService的构造方法:原始代码里构造方法的类名写错成了UserSshKeyService,这个错误会导致Mockito无法正常实例化对象,也是空指针的潜在诱因。
  • 必须给测试类添加Mockito的运行器/扩展注解,否则@Mock、@InjectMocks等注解不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:47:20