package com.example.erp.module.usr; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.example.erp.common.exception.BizException; import com.example.erp.common.vo.PageVO; import com.example.erp.config.UserPrincipal; import com.example.erp.module.usr.dto.UserCreateReqDTO; import com.example.erp.module.usr.dto.UserListQueryDTO; import com.example.erp.module.usr.dto.UserUpdateReqDTO; import com.example.erp.module.usr.vo.UserListItemVO; import com.example.erp.module.usr.vo.UserUpdateRespVO; import com.example.erp.module.usr.entity.StaffEntity; import com.example.erp.module.usr.entity.UsrUserEntity; import com.example.erp.module.usr.entity.UserPermissionEntity; import com.example.erp.module.usr.mapper.PermissionGroupMapper; import com.example.erp.module.usr.mapper.StaffMapper; import com.example.erp.common.constants.UsrErrorCode; import com.example.erp.module.usr.mapper.UserPermissionMapper; import com.example.erp.module.usr.mapper.UsrUserMapper; import com.example.erp.module.usr.service.impl.UserServiceImpl; import com.example.erp.module.usr.vo.UserCreateRespVO; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UsrUserMapper userMapper; @Mock private StaffMapper staffMapper; @Mock private PermissionGroupMapper permGroupMapper; @Mock private UserPermissionMapper userPermissionMapper; @Mock private BCryptPasswordEncoder passwordEncoder; @InjectMocks private UserServiceImpl userService; private UserCreateReqDTO req; private UserPrincipal superAdmin; private UserPrincipal normalUser; @BeforeEach void setUp() { req = new UserCreateReqDTO(); req.setUserCode("UC001"); req.setUsername("testuser"); req.setUserType("普通用户"); req.setLanguage("中文"); superAdmin = new UserPrincipal("u1", "admin", "超级管理员", "b1"); normalUser = new UserPrincipal("u2", "user", "普通用户", "b1"); } @Test void createUser_normalUser_throws40300() { BizException ex = assertThrows(BizException.class, () -> userService.createUser(req, normalUser)); assertEquals(40300, ex.getCode()); } @Test void createUser_success_insertsUserAndReturnsVO() { when(userMapper.selectCount(any())).thenReturn(0L); when(passwordEncoder.encode(anyString())).thenReturn("$2a$10$hashed"); when(userMapper.insert(any(UsrUserEntity.class))).thenReturn(1); UserCreateRespVO vo = userService.createUser(req, superAdmin); assertNotNull(vo.getUserId()); assertEquals("UC001", vo.getUserCode()); assertEquals("testuser", vo.getUsername()); verify(userMapper).insert(any(UsrUserEntity.class)); } @Test void createUser_duplicateUserCode_throws40902() { when(userMapper.selectCount(any())).thenReturn(1L); BizException ex = assertThrows(BizException.class, () -> userService.createUser(req, superAdmin)); assertEquals(40902, ex.getCode()); } @Test void createUser_duplicateUsername_throws40901() { when(userMapper.selectCount(any())).thenReturn(0L, 1L); BizException ex = assertThrows(BizException.class, () -> userService.createUser(req, superAdmin)); assertEquals(40901, ex.getCode()); } @Test @SuppressWarnings("unchecked") void createUser_withPermGroups_insertsPermissions() { req.setPermGroupIds(List.of("g1", "g2")); when(userMapper.selectCount(any())).thenReturn(0L); when(passwordEncoder.encode(anyString())).thenReturn("$2a$10$hashed"); when(userMapper.insert(any(UsrUserEntity.class))).thenReturn(1); userService.createUser(req, superAdmin); verify(userPermissionMapper).insert(argThat((java.util.Collection c) -> c.size() == 2)); } @Test void getUserList_queryDtoDefaults() { UserListQueryDTO q = new UserListQueryDTO(); assertEquals("username", q.getQueryField()); assertEquals("contains", q.getMatchType()); assertEquals(20, q.getPageSize()); assertEquals(1, q.getPage()); } @Test void getUserList_capsPageSizeAt100_callsMapper() { IPage mockPage = new Page<>(1, 100, 5); when(userMapper.selectUserList(argThat(p -> p.getSize() == 100), eq("b1"), any(), any(), any())) .thenReturn(mockPage); UserListQueryDTO q = new UserListQueryDTO(); q.setPageSize(200); PageVO result = userService.getUserList(q, "b1"); assertEquals(5L, result.getTotal()); verify(userMapper).selectUserList(argThat(p -> p.getSize() == 100), eq("b1"), any(), any(), any()); } @Test void getUserList_emptyQueryValue_doesNotFilter() { IPage mockPage = new Page<>(1, 20, 2); when(userMapper.selectUserList(any(), eq("b1"), eq("username"), eq("contains"), eq(""))) .thenReturn(mockPage); UserListQueryDTO q = new UserListQueryDTO(); q.setQueryValue(null); PageVO result = userService.getUserList(q, "b1"); assertEquals(2L, result.getTotal()); } @Test void createUser_invalidEmployeeId_throws40001() { req.setEmployeeId("bad-staff-id"); when(userMapper.selectCount(any())).thenReturn(0L); when(staffMapper.selectOne(any())).thenReturn(null); BizException ex = assertThrows(BizException.class, () -> userService.createUser(req, superAdmin)); assertEquals(UsrErrorCode.EMPLOYEE_NOT_FOUND, ex.getCode()); } @Test void updateUser_dtoDefaults() { com.example.erp.module.usr.dto.UserUpdateReqDTO dto = new com.example.erp.module.usr.dto.UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setCanEditDoc(false); dto.setDisabled(false); dto.setEmployeeId(null); dto.setPermGroupIds(List.of()); assertEquals("普通用户", dto.getUserType()); assertEquals("中文", dto.getLanguage()); assertFalse(dto.isCanEditDoc()); assertFalse(dto.isDisabled()); assertNull(dto.getEmployeeId()); assertTrue(dto.getPermGroupIds().isEmpty()); com.example.erp.module.usr.vo.UserUpdateRespVO resp = new com.example.erp.module.usr.vo.UserUpdateRespVO(); resp.setUserId("u1"); resp.setUsername("alice"); resp.setUpdatedAt(java.time.LocalDateTime.now()); assertEquals("u1", resp.getUserId()); assertEquals("alice", resp.getUsername()); assertNotNull(resp.getUpdatedAt()); assertEquals(40400, UsrErrorCode.USER_NOT_FOUND); assertEquals(40301, UsrErrorCode.SELF_ADMIN_CHANGE); } @Test void updateUser_nonAdmin_throws40300() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setPermGroupIds(List.of()); BizException ex = assertThrows(BizException.class, () -> userService.updateUser("u-target", dto, normalUser)); assertEquals(UsrErrorCode.PERMISSION_DENIED, ex.getCode()); } @Test void updateUser_userNotFound_throws40400() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setPermGroupIds(List.of()); when(userMapper.selectOne(any())).thenReturn(null); BizException ex = assertThrows(BizException.class, () -> userService.updateUser("u-target", dto, superAdmin)); assertEquals(UsrErrorCode.USER_NOT_FOUND, ex.getCode()); } @Test void updateUser_selfAdminChange_throws40301() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setPermGroupIds(List.of()); UsrUserEntity existing = new UsrUserEntity(); existing.setSId("u1"); existing.setSUsername("admin"); when(userMapper.selectOne(any())).thenReturn(existing); // superAdmin.userId() == "u1", target userId == "u1" → self-admin change BizException ex = assertThrows(BizException.class, () -> userService.updateUser("u1", dto, superAdmin)); assertEquals(UsrErrorCode.SELF_ADMIN_CHANGE, ex.getCode()); } @Test void updateUser_invalidEmployee_throws40001() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setEmployeeId("bad-emp"); dto.setPermGroupIds(List.of()); UsrUserEntity existing = new UsrUserEntity(); existing.setSId("u-target"); existing.setSUsername("alice"); when(userMapper.selectOne(any())).thenReturn(existing); when(staffMapper.selectOne(any())).thenReturn(null); BizException ex = assertThrows(BizException.class, () -> userService.updateUser("u-target", dto, superAdmin)); assertEquals(UsrErrorCode.EMPLOYEE_NOT_FOUND, ex.getCode()); } @Test void updateUser_happyPath_updatesAndReturnsResp() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("超级管理员"); dto.setLanguage("英文"); dto.setCanEditDoc(true); dto.setDisabled(false); dto.setPermGroupIds(List.of("g1", "g2")); UsrUserEntity existing = new UsrUserEntity(); existing.setSId("u-target"); existing.setSUsername("alice"); when(userMapper.selectOne(any())).thenReturn(existing); when(userMapper.update(any(), any())).thenReturn(1); when(userPermissionMapper.delete(any())).thenReturn(0); UserUpdateRespVO resp = userService.updateUser("u-target", dto, superAdmin); assertNotNull(resp); assertEquals("u-target", resp.getUserId()); assertEquals("alice", resp.getUsername()); assertNotNull(resp.getUpdatedAt()); verify(userMapper).update(any(), any()); verify(userPermissionMapper).delete(any()); verify(userPermissionMapper).insert(argThat((java.util.Collection c) -> c.size() == 2)); } @Test void updateUser_emptyPermGroupIds_onlyDeletes() { UserUpdateReqDTO dto = new UserUpdateReqDTO(); dto.setUserType("普通用户"); dto.setLanguage("中文"); dto.setPermGroupIds(List.of()); UsrUserEntity existing = new UsrUserEntity(); existing.setSId("u-target"); existing.setSUsername("bob"); when(userMapper.selectOne(any())).thenReturn(existing); when(userMapper.update(any(), any())).thenReturn(1); when(userPermissionMapper.delete(any())).thenReturn(0); userService.updateUser("u-target", dto, superAdmin); verify(userPermissionMapper).delete(any()); verify(userPermissionMapper, never()).insert(anyList()); } }