Mockito测试JPA Service时,Repository的findById返回空Optional引发异常
解决Mockito测试editUser方法时的NoSuchElementException异常
问题根源
你的测试代码仅Mock了userRepository.save()方法,但未MockfindById()方法。当Service执行userRepository.findById(user.getUser_id()).get()时,findById返回空Optional,直接调用get()就会触发NoSuchElementException。
修复测试代码
需要在测试中补充对findById()的Mock,让它返回包含预设原有用户的Optional。修改后的测试代码如下:
@Test void checkIfUserCanBeEdited(){ // Mock findById,返回setup中创建的原有用户 given(userRepository.findById(user.getUser_id())).willReturn(Optional.of(user)); // 模拟保存后的返回结果(匹配任意User对象,返回加密密码后的用户) User expectedUser = new User( user.getUser_id(), user.getUsername(), passwordEncoder.encode("check"), user.getGroup_id(), user.getEmail(), "user", user.getActive() ); given(userRepository.save(any(User.class))).willReturn(expectedUser); // 修改传入的用户属性 user.setPassword("check"); user.setRole("user"); // 执行方法 User updateUser = userService.editUser(user); // 断言验证 assertThat(updateUser.getPassword()).isEqualTo(passwordEncoder.encode("check")); assertThat(updateUser.getRole()).isEqualTo("user"); }
注意:Service中对非空密码会执行加密操作,所以断言时要对比加密后的密码,而非明文"check",否则断言会失败。
优化Service代码(推荐)
原Service直接调用get()获取Optional值,未处理空值场景,生产环境也可能抛出异常。建议优化为:
@Override public User editUser(User user) { // 找不到用户时抛出明确的业务异常 User savedUser = userRepository.findById(user.getUser_id()) .orElseThrow(() -> new IllegalArgumentException("用户不存在,ID:" + user.getUser_id())); User userToEdit = new User(); userToEdit.setUser_id(user.getUser_id()); userToEdit.setRole(user.getRole().isEmpty() ? savedUser.getRole() : user.getRole()); userToEdit.setUsername(user.getUsername().isEmpty() ? savedUser.getUsername() : user.getUsername()); userToEdit.setPassword(user.getPassword().isEmpty() ? savedUser.getPassword() : passwordEncoder.encode(user.getPassword())); userToEdit.setEmail(user.getEmail().isEmpty() ? savedUser.getEmail() : user.getEmail()); userToEdit.setGroup_id((user.getGroup_id() == -1) ? savedUser.getGroup_id() : user.getGroup_id()); userToEdit.setActive(user.getActive() != savedUser.getActive() ? savedUser.getActive() : user.getActive()); return userRepository.save(userToEdit); }
优化后无论测试还是生产环境,用户不存在时都会抛出更清晰的业务异常,而非泛化的NoSuchElementException。
内容的提问来源于stack exchange,提问作者m3k_1
相关产品推荐
相关产品推荐

