Spring Boot服务层单元测试调用方法时出现NullPointerException的解决方法
问题修复方案
报错原因分析
报错NullPointerException: Cannot invoke "updatedUserDto.setId(...)" because "updatedUserDto" is null,本质是**userMapper.toEntity(userDto)返回了null**,同时测试代码还存在mock参数不匹配的问题,导致逻辑执行不符合预期。
具体修复步骤
- 补充
userMapper.toEntity的mock逻辑
服务层代码中两次调用了userMapper.toEntity(userDto),但你的测试只mock了toDto方法,没有mocktoEntity,导致该方法默认返回null。需要添加以下mock代码:
when(userMapper.toEntity(userDto)).thenReturn(userEntity);
- 修正
userRepository.findByUserIdAndType的mock参数
测试中用UUID.randomUUID()作为查询参数,但实际服务层调用时传入的是你预先设置的userDto的ID(固定值),两者不匹配,导致mock的查询结果不会触发。需要改用匹配器保证参数一致:
// 先导入Mockito的静态方法import static org.mockito.ArgumentMatchers.eq; when(userRepository.findByUserIdAndType(eq(userDto.getUserId()), eq(UserTypes.ACTIF))) .thenReturn(Optional.of(userEntity));
- 检查字段名一致性
服务层调用的是userDto.getUserId(),但测试里设置的是userDto.setId(UUID.randomUUID()),确认UserDto类的字段是userId还是id:
- 如果字段是
userId,测试里要改成userDto.setUserId(UUID.randomUUID()),否则getUserId()会返回null,导致查询参数不匹配。
修复后的完整测试代码
@Test void whencreateOrUpdateUser() { // Given final var userDto = new UserDto(); userDto.setUserId(UUID.randomUUID()); // 修正字段名,根据实际类调整 userDto.setName("toto"); final var userEntity = mock(UserEntity.class); // 修正mock参数,匹配实际传入的userDto的userId when(userRepository.findByUserIdAndType(eq(userDto.getUserId()), eq(UserTypes.ACTIF))) .thenReturn(Optional.of(userEntity)); when(userRepository.save(userEntity)).thenReturn(userEntity); when(userMapper.toEntity(userDto)).thenReturn(userEntity); // 新增toEntity的mock when(userMapper.toDto(userEntity)).thenReturn(userDto); // When final var result = service.createOrUpdateUser(userDto); // Then assertEquals(result, userDto); }
额外注意点
服务层中使用了静态调用UserMapper.toDto(newUser),但测试里mock的是实例userMapper的方法,这会导致静态调用无法被mock。如果是这种情况,建议把UserMapper改为依赖注入的实例(比如用@Autowired注入),而非静态类,这样才能正常被Mockito mock。
内容的提问来源于stack exchange,提问作者lnikoli31
相关产品推荐
相关产品推荐

