Spring Boot Service测试问题:getUser方法if分支未被覆盖
问题:Spring Boot测试中getUser方法的if分支未被代码覆盖
待测试的getUser方法:
public Optional<UserDto> getUser(String username) { Optional<User> userOptional = this.userRepository.findById(username); if (userOptional.isPresent()) { UserDto userDto = this.convert(userOptional.get()); return Optional.of(userDto); } return Optional.empty(); }
编写了测试用例,但代码覆盖率显示if语句内部代码未被覆盖,测试代码如下:
@Test void getUserShouldReturnAnOptionalOfUserDtoIfItIsFound() { Optional<UserDto> userDtoOptional = this.underTest.getUser(user.getUsername()); Mockito.verify(userRepository).findById(user.getUsername()); userDtoOptional.ifPresent(userDto -> Assertions.assertThat(userDto).isInstanceOf(UserDto.class)); } @Test void getUserTestShouldReturnOptionalEmptyWhenUserIsNotFound() { String username = "johndoe"; Optional<UserDto> userDtoOptional = this.underTest.getUser(username); Mockito.verify(userRepository).findById(username); userDtoOptional.ifPresent(userDto -> Assertions.assertThat(userDto).isInstanceOf(Optional.empty().getClass())); }
解决方案
1. 修复「用户存在」场景的测试用例
第一个测试用例未模拟userRepository.findById的返回值,导致实际执行时userOptional大概率为空,if分支根本没进入。需要添加模拟逻辑让findById返回存在的User对象,同时模拟convert方法的返回:
@Test void getUserShouldReturnAnOptionalOfUserDtoIfItIsFound() { // 1. 模拟userRepository查询到用户 User mockUser = new User(); mockUser.setUsername("testUser"); when(userRepository.findById(mockUser.getUsername())).thenReturn(Optional.of(mockUser)); // 2. 模拟convert方法返回UserDto UserDto mockUserDto = new UserDto(); when(underTest.convert(mockUser)).thenReturn(mockUserDto); // 3. 执行测试方法 Optional<UserDto> userDtoOptional = this.underTest.getUser(mockUser.getUsername()); // 4. 验证与断言 Mockito.verify(userRepository).findById(mockUser.getUsername()); Assertions.assertThat(userDtoOptional).isPresent(); Assertions.assertThat(userDtoOptional.get()).isEqualTo(mockUserDto); }
2. 修复「用户不存在」场景的测试用例
原测试用例里的ifPresent断言永远不会执行(因为返回的是空Optional),且断言逻辑错误,应直接验证返回值为空:
@Test void getUserShouldReturnOptionalEmptyWhenUserIsNotFound() { String username = "johndoe"; // 模拟userRepository查询不到用户 when(userRepository.findById(username)).thenReturn(Optional.empty()); Optional<UserDto> userDtoOptional = this.underTest.getUser(username); Mockito.verify(userRepository).findById(username); Assertions.assertThat(userDtoOptional).isEmpty(); }
关键说明
- 测试Spring Boot的Service层时,必须模拟依赖组件的返回值(比如
userRepository),否则会使用真实实现(未正确配置时可能返回空或抛出异常),导致分支无法覆盖。 - 断言要直接验证结果的状态(
isPresent()/isEmpty())和内容,避免在ifPresent中写断言(空Optional时不会执行,无法验证空场景)。
内容的提问来源于stack exchange,提问作者dave25
相关产品推荐
相关产品推荐

