编写@Post方法JUnit测试用例时userService.addUser报空指针且save返回null
问题排查与解决方案
核心问题原因
- ConverterService的Mock参数不匹配
测试代码中Mockito.when(converterService.convertToEntity(new UserDto())).thenReturn(user)要求方法入参必须是当前new的空UserDto实例,但实际调用addUser时传入的是手动赋值了userId、userName的userDto对象,两个对象不是同一个实例,Mockito匹配失败后convertToEntity默认返回null,后续调用convertedUser.setUserId会直接触发空指针。 - UserRepository的Mock参数不匹配
就算convertToEntity返回了mock的user对象,后续代码还会调用convertedUser.setUserName(userdto.getUserName())把用户名从初始的ABC修改为AB,你Mock时写的Mockito.when(userRepository.save(user)).thenReturn(user)要求入参是初始的user对象(用户名ABC),和实际传入save方法的修改后对象不匹配,Mockito匹配失败后返回默认null,最终导致addUser返回null。 - Mock对象未注入到Spring上下文
你给ConverterService加的是@Mock注解,该注解只会创建Mock对象,不会替换Spring上下文里UserService依赖的ConverterService实例,实际运行时UserService调用的还是原生的ConverterService,不是你Mock的对象。
修正方案
修正后的测试代码
@RunWith(SpringRunner.class) @SpringBootTest public class UserServiceTest { @Autowired private UserService userService; // 改为MockBean替换Spring上下文内的ConverterService实例 @MockBean private ConverterService converterService; @MockBean private UserRepository userRepository; @Test public void addUserTest() { UserDto userDto = new UserDto(); userDto.setUserId("123"); userDto.setUserName("AB"); User user = new User("123","ABC"); // 匹配实际传入的userDto对象,也可使用any(UserDto.class)做任意匹配 Mockito.when(converterService.convertToEntity(userDto)).thenReturn(user); // 用any(User.class)匹配任意User实例,避免属性修改后匹配失败 Mockito.when(userRepository.save(Mockito.any(User.class))).thenReturn(user); User savedUser = userService.addUser(userDto); Assert.assertEquals(user, savedUser); } }
如果需要严格校验save方法的入参属性,可使用Mockito.argThat自定义匹配规则:
Mockito.when(userRepository.save(Mockito.argThat(savedUser -> "123".equals(savedUser.getUserId()) && "AB".equals(savedUser.getUserName()) ))).thenReturn(user);
内容的提问来源于stack exchange,提问作者Dheeraj kumar
相关产品推荐
相关产品推荐

