You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:55:40