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

如何为从数据库取值的UserServiceImpl的getUserDetails方法编写JUnit测试

UserServiceImpl.getUserDetails 方法JUnit测试实现方案

现有测试存在的问题

  • 实例化顺序错误:先调用userService.getUserDetails()再实例化UserServiceImpl,会直接抛出空指针异常
  • 调用方法错误:执行的是未实现的无参getUserDetails()方法,未覆盖核心的带参业务方法
  • 断言无业务意义:仅对比两个固定相同的字符串,未验证任何业务逻辑正确性

推荐实现方案

我们优先采用单元测试+Mock依赖的方案,不需要依赖真实数据库,测试执行速度快、稳定性高;如果需要验证数据库交互逻辑,再选用集成测试方案。

方案1:单元测试(Mockito实现)

前置依赖

确保项目引入JUnit 5 + Mockito测试依赖,Maven配置参考:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>4.11.0</version>
    <scope>test</scope>
</dependency>

完整测试代码

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
public class UserServiceImplTest {

    // Mock所有外部依赖服务
    @Mock
    private SubsidiaryService subsidiaryService;
    @Mock
    private UserGroupService userGroupService;
    @Mock
    private ProjectService projectService;

    // 注入Mock依赖到待测类,如果getUserDetailsById是自身方法请将@InjectMocks改为@Spy
    @InjectMocks
    private UserServiceImpl userService;

    @Test
    public void testGetUserDetails_WithValidUserId_ReturnCorrectData() {
        // 1. 构造测试数据
        String testUserId = "O635";
        // 构造模拟返回的UserDTO
        UserDTO mockUserDTO = new UserDTO();
        mockUserDTO.setUsrCf("O635");
        mockUserDTO.setRsqnamCf("test_login");
        mockUserDTO.setRsqsecprfCf("ADMIN");
        mockUserDTO.setLstupdD(new Date());
        mockUserDTO.setRsqpwdCf("test_pwd");
        mockUserDTO.setCreusrCf("test_creator");
        // 构造模拟返回的用户组列表
        UserGroupDTO mockGroupDTO = new UserGroupDTO();
        mockGroupDTO.setNameLl("管理员组");
        List<UserGroupDTO> mockGroupList = List.of(mockGroupDTO);
        // 构造模拟返回的项目列表、子公司列表按需补充
        List<Project> mockProjectList = new ArrayList<>();
        List<ProjDetail> mockProjDetailList = new ArrayList<>();
        List<Subsidiary> mockSubsidiaryList = new ArrayList<>();

        // 2. 打桩Mock依赖的返回值
        when(subsidiaryService.listSubsidariesByUserId(null)).thenReturn(mockSubsidiaryList);
        when(userService.getUserDetailsById(testUserId)).thenReturn(mockUserDTO);
        when(userGroupService.listUserGroupByUserId(testUserId)).thenReturn(mockGroupList);
        when(projectService.listProjectsByUserId(null)).thenReturn(mockProjectList);
        when(projectService.aggregateProjectDetails(anyList())).thenReturn(mockProjDetailList);

        // 3. 调用待测方法
        AntaresUserDetials result = userService.getUserDetails(testUserId);

        // 4. 断言返回结果符合预期
        assertNotNull(result);
        assertEquals("O635", result.getId());
        assertEquals("sss", result.getFirstName());
        assertEquals("sss", result.getLastName());
        assertEquals("test_login", result.getLoginId());
        assertEquals("ADMIN", result.getUserType());
        assertEquals("ADMIN", result.getSecurityProfile().getName());
        assertTrue(result.getSecurityProfile().isSelected());
        assertEquals(1, result.getUsergroups().size());
        assertEquals("管理员组", result.getUsergroups().get(0).getName());
        assertTrue(result.getUsergroups().get(0).isSelected());
    }
}

方案2:集成测试(连接真实测试库)

如果需要验证和数据库的交互逻辑,按以下步骤实现:

  • 配置测试环境的数据源,指向专门的测试库,避免影响生产数据
  • 测试执行前提前在测试库中插入userId为O635的用户、用户组、子公司、项目等关联测试数据
  • 启动Spring上下文,注入真实的UserServiceImpl实例
  • 调用方法后,断言返回的字段值和数据库中存储的数值完全一致

内容的提问来源于stack exchange,提问作者Ayushi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:09:03