liu
2026-10-28 cc5438a25896d19f02b652865781dc443b274354
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package cn.iocoder.yudao.module.hrm.service.employee;
 
import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeSaveReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEducationMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEmergencyContactMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeWorkHistoryMapper;
import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.mes.api.cal.MesCalTeamApi;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserSyncReqDTO;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
 
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
 
/**
 * 员工删除/修改 -> 系统账号 同步单元测试
 */
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class HrmEmployeeServiceImplSyncTest {
 
    private static final Long EMPLOYEE_ID = 1L;
    private static final Long USER_ID = 200L;
 
    @Mock
    private HrmEmployeeMapper employeeMapper;
    @Mock
    private HrmEmployeeEducationMapper educationMapper;
    @Mock
    private HrmEmployeeWorkHistoryMapper workHistoryMapper;
    @Mock
    private HrmEmployeeEmergencyContactMapper emergencyContactMapper;
    @Mock
    private HrmNoRedisDAO noRedisDAO;
    @Mock
    private DeptApi deptApi;
    @Mock
    private PostApi postApi;
    @Mock
    private AdminUserApi adminUserApi;
    @Mock
    private RoleApi roleApi;
    @Mock
    private MesCalTeamApi mesCalTeamApi;
    @Mock
    private ConfigApi configApi;
    @Mock
    private HrmEmployeeService self;
 
    @InjectMocks
    private HrmEmployeeServiceImpl service;
 
    private HrmEmployeeDO employee(Long id, Long userId) {
        return HrmEmployeeDO.builder().id(id).userId(userId).build();
    }
 
    // ==================== 删除员工 ====================
 
    @Test
    @DisplayName("删除员工:已绑定账号时,联动删除系统账号")
    void deleteEmployee_withUser_deleteAccount() {
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(employee(EMPLOYEE_ID, USER_ID));
        when(employeeMapper.selectCount(any(SFunction.class), eq(USER_ID))).thenReturn(1L);
 
        service.deleteEmployee(EMPLOYEE_ID);
 
        verify(adminUserApi).deleteUserSilently(USER_ID);
        verify(educationMapper).deleteByEmployeeId(EMPLOYEE_ID);
        verify(workHistoryMapper).deleteByEmployeeId(EMPLOYEE_ID);
        verify(emergencyContactMapper).deleteByEmployeeId(EMPLOYEE_ID);
        verify(employeeMapper).deleteById(EMPLOYEE_ID);
    }
 
    @Test
    @DisplayName("删除员工:未绑定账号时,不调用账号删除")
    void deleteEmployee_noUser_skip() {
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(employee(EMPLOYEE_ID, null));
 
        service.deleteEmployee(EMPLOYEE_ID);
 
        verify(adminUserApi, never()).deleteUserSilently(anyLong());
        verify(employeeMapper).deleteById(EMPLOYEE_ID);
    }
 
    @Test
    @DisplayName("删除员工:账号是内置 admin(id=1) 时,不删除账号")
    void deleteEmployee_adminUser_skip() {
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(employee(EMPLOYEE_ID, 1L));
 
        service.deleteEmployee(EMPLOYEE_ID);
 
        verify(adminUserApi, never()).deleteUserSilently(anyLong());
        verify(employeeMapper).deleteById(EMPLOYEE_ID);
    }
 
    @Test
    @DisplayName("删除员工:账号被多条员工档案引用时,不删除账号")
    void deleteEmployee_multiEmployees_skip() {
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(employee(EMPLOYEE_ID, USER_ID));
        when(employeeMapper.selectCount(any(SFunction.class), eq(USER_ID))).thenReturn(2L);
 
        service.deleteEmployee(EMPLOYEE_ID);
 
        verify(adminUserApi, never()).deleteUserSilently(anyLong());
        verify(employeeMapper).deleteById(EMPLOYEE_ID);
    }
 
    // ==================== 修改员工 ====================
 
    @Test
    @DisplayName("修改员工:把可对应字段同步到账号")
    void updateEmployee_syncToAccount() {
        HrmEmployeeDO old = HrmEmployeeDO.builder()
                .id(EMPLOYEE_ID).userId(USER_ID).name("旧名").phone("13800000000")
                .deptId(10L).gender(1).email("old@x.com").build();
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(old);
        when(employeeMapper.selectByPhone("13900000000")).thenReturn(null);
 
        HrmEmployeeSaveReqVO reqVO = new HrmEmployeeSaveReqVO();
        reqVO.setId(EMPLOYEE_ID);
        reqVO.setName("新名");
        reqVO.setPhone("13900000000");
        reqVO.setDeptId(11L);
        reqVO.setPostId(2L);
        reqVO.setGender(2);
        reqVO.setEmail("new@x.com");
 
        service.updateEmployee(reqVO);
 
        ArgumentCaptor<AdminUserSyncReqDTO> captor = ArgumentCaptor.forClass(AdminUserSyncReqDTO.class);
        verify(adminUserApi).updateUserForEmployee(captor.capture());
        AdminUserSyncReqDTO dto = captor.getValue();
        assertEquals(USER_ID, dto.getUserId());
        assertEquals("新名", dto.getNickname());
        assertEquals("13900000000", dto.getMobile());
        assertEquals(11L, dto.getDeptId());
        assertEquals(2, dto.getSex());
        assertEquals("new@x.com", dto.getEmail());
    }
 
    @Test
    @DisplayName("修改员工:未绑定账号时,不同步账号")
    void updateEmployee_noUser_skip() {
        HrmEmployeeDO old = HrmEmployeeDO.builder()
                .id(EMPLOYEE_ID).userId(null).name("旧名").phone("13800000000")
                .deptId(10L).gender(1).build();
        when(employeeMapper.selectById(EMPLOYEE_ID)).thenReturn(old);
 
        HrmEmployeeSaveReqVO reqVO = new HrmEmployeeSaveReqVO();
        reqVO.setId(EMPLOYEE_ID);
        reqVO.setName("新名");
        reqVO.setPhone("13800000000");
        reqVO.setDeptId(10L);
        reqVO.setPostId(2L);
        reqVO.setGender(1);
 
        service.updateEmployee(reqVO);
 
        verify(adminUserApi, never()).updateUserForEmployee(any());
    }
 
}