Spring Boot Mockito测试中JPA Repository返回Null致空指针问题求助
问题分析与解决方案
核心原因
你遇到的问题本质是服务类中的Repository依赖未正确绑定到Mockito模拟对象,导致你配置的when(...).thenAnswer()逻辑未生效,Mock对象默认返回null,进而触发空指针异常。
分步解决方案
1. 为服务实例添加@InjectMocks注解
在测试类中,必须将你创建的所有@Mock依赖注入到目标服务实例中,否则服务会使用未初始化的真实依赖(或null),而非你配置的模拟对象。
修改后的完整测试类代码:
@ExtendWith(MockitoExtension.class) // 替代手动初始化,更简洁稳定 public class UserServiceImplTest { @Mock private UserRepository userRepository; @Mock private UserRoleRepository userRoleRepository; @Mock private CustomerRepository customerRepository; @Mock private PasswordEncoder passwordEncoder; // 关键:让Mockito自动将所有@Mock依赖注入到服务实例中 @InjectMocks private UserServiceImpl userService; @Test public void testRegisterCustomerSuccess() { // Mock数据 SignupRequest signupRequest = createSignupRequest(); when(userRepository.findByUsernameOrEmail(signupRequest.getEmail())).thenReturn(Optional.empty()); when(passwordEncoder.encode(signupRequest.getPassword())).thenReturn("encodedPassword"); when(userRepository.save(any(User.class))).thenAnswer(invocation -> { User user = invocation.getArgument(0); user.setId(1L); return user; }); when(userRoleRepository.save(any(UserRole.class))).thenAnswer(invocation -> { UserRole role = invocation.getArgument(0); role.setUserRoleId(1L); return role; }); when(customerRepository.save(any(Customer.class))).thenAnswer(invocation -> { Customer customer = invocation.getArgument(0); customer.setId(1L); return customer; }); // 调用服务方法 assertDoesNotThrow(() -> userService.registerCustomer(signupRequest)); // 验证交互 verify(userRepository).findByUsernameOrEmail(signupRequest.getEmail()); verify(passwordEncoder).encode(signupRequest.getPassword()); verify(userRepository).save(any(User.class)); verify(userRoleRepository).save(any(UserRole.class)); verify(customerRepository).save(any(Customer.class)); } // 实现测试数据构造方法 private SignupRequest createSignupRequest() { SignupRequest request = new SignupRequest(); request.setEmail("test@example.com"); request.setPassword("123456"); // 补充其他必要字段 return request; } }
2. 验证依赖注入有效性
调试时可添加以下代码,确认服务中的Repository是Mockito代理对象:
System.out.println(userRepository.getClass()); // 输出应为org.mockito...MockitoProxy相关类型
若输出为真实Repository实现类(如JpaRepository的代理类),说明注入失败,需检查:
- 服务类的构造函数是否包含所有需要注入的Repository依赖(Mockito优先通过构造函数注入)
- 服务类中的依赖字段是否为
private且未被手动初始化
3. 兜底排查:确认Mock方法匹配逻辑
若注入正常但仍返回null,检查when()中的匹配器是否与服务调用的参数匹配:
- 确认服务中调用
save时的参数确实是User类型(避免子类/代理类导致any(User.class)不匹配) - 可临时替换为
any()匹配器验证,再逐步缩小匹配范围
额外建议
- 优先使用
@ExtendWith(MockitoExtension.class)替代手动调用MockitoAnnotations.openMocks(this),减少初始化代码 - 确保JPA Repository接口继承自Spring Data的
Repository或其子接口,保证Mockito能正确生成代理对象
内容的提问来源于stack exchange,提问作者Prince Lathiya
相关产品推荐
相关产品推荐

