Commit 0f608dff7b9d4d7f94b4bbb2a46a5ebb338e410d
1 parent
71b613d6
feat(usr): createUser 唯一性预检 (40002/40003) REQ-USR-001
Showing
2 changed files
with
50 additions
and
1 deletions
backend/src/main/java/com/xly/test4/module/usr/service/impl/UserServiceImpl.java
| 1 | 1 | package com.xly.test4.module.usr.service.impl; |
| 2 | 2 | |
| 3 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 4 | +import com.xly.test4.common.exception.BusinessException; | |
| 5 | +import com.xly.test4.common.response.ResultCode; | |
| 3 | 6 | import com.xly.test4.common.security.CurrentUser; |
| 4 | 7 | import com.xly.test4.common.security.CurrentUserContext; |
| 5 | 8 | import com.xly.test4.module.usr.converter.UserConverter; |
| ... | ... | @@ -36,6 +39,15 @@ public class UserServiceImpl implements UserService { |
| 36 | 39 | public UserCreateVO createUser(UserCreateDTO dto) { |
| 37 | 40 | CurrentUser current = CurrentUserContext.current(); |
| 38 | 41 | |
| 42 | + if (userMapper.selectCount(new LambdaQueryWrapper<User>() | |
| 43 | + .eq(User::getSUserName, dto.getUserName())) > 0) { | |
| 44 | + throw new BusinessException(ResultCode.USER_NAME_DUPLICATE, "用户名已存在"); | |
| 45 | + } | |
| 46 | + if (userMapper.selectCount(new LambdaQueryWrapper<User>() | |
| 47 | + .eq(User::getSUserCode, dto.getUserCode())) > 0) { | |
| 48 | + throw new BusinessException(ResultCode.USER_CODE_DUPLICATE, "用户号已存在"); | |
| 49 | + } | |
| 50 | + | |
| 39 | 51 | User user = userConverter.toEntity(dto); |
| 40 | 52 | user.setSBrandsId(current.getBrandsId()); |
| 41 | 53 | user.setSSubsidiaryId(current.getSubsidiaryId()); | ... | ... |
backend/src/test/java/com/xly/test4/module/usr/service/impl/UserServiceImplTest.java
| 1 | 1 | package com.xly.test4.module.usr.service.impl; |
| 2 | 2 | |
| 3 | +import com.baomidou.mybatisplus.core.conditions.Wrapper; | |
| 4 | +import com.xly.test4.common.exception.BusinessException; | |
| 3 | 5 | import com.xly.test4.common.security.CurrentUser; |
| 4 | 6 | import com.xly.test4.common.security.CurrentUserContext; |
| 5 | 7 | import com.xly.test4.module.usr.converter.UserConverter; |
| ... | ... | @@ -18,9 +20,12 @@ import org.springframework.security.crypto.password.PasswordEncoder; |
| 18 | 20 | import java.util.List; |
| 19 | 21 | |
| 20 | 22 | import static org.assertj.core.api.Assertions.assertThat; |
| 23 | +import static org.assertj.core.api.Assertions.assertThatThrownBy; | |
| 21 | 24 | import static org.mockito.ArgumentMatchers.any; |
| 22 | 25 | import static org.mockito.Mockito.mock; |
| 23 | 26 | import static org.mockito.Mockito.mockStatic; |
| 27 | +import static org.mockito.Mockito.never; | |
| 28 | +import static org.mockito.Mockito.verify; | |
| 24 | 29 | import static org.mockito.Mockito.when; |
| 25 | 30 | |
| 26 | 31 | class UserServiceImplTest { |
| ... | ... | @@ -64,6 +69,7 @@ class UserServiceImplTest { |
| 64 | 69 | return dto; |
| 65 | 70 | } |
| 66 | 71 | |
| 72 | + @SuppressWarnings("unchecked") | |
| 67 | 73 | private void stubConverterReturnsEmptyUser() { |
| 68 | 74 | when(userConverter.toEntity(any(UserCreateDTO.class))).thenAnswer(inv -> new User()); |
| 69 | 75 | when(userConverter.toVO(any(User.class))).thenAnswer(inv -> { |
| ... | ... | @@ -75,6 +81,7 @@ class UserServiceImplTest { |
| 75 | 81 | u.setIIncrement(42); |
| 76 | 82 | return 1; |
| 77 | 83 | }); |
| 84 | + when(userMapper.selectCount(any(Wrapper.class))).thenReturn(0L); | |
| 78 | 85 | } |
| 79 | 86 | |
| 80 | 87 | @Test |
| ... | ... | @@ -110,7 +117,37 @@ class UserServiceImplTest { |
| 110 | 117 | service.createUser(dto); |
| 111 | 118 | |
| 112 | 119 | ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class); |
| 113 | - org.mockito.Mockito.verify(userMapper).insert(captor.capture()); | |
| 120 | + verify(userMapper).insert(captor.capture()); | |
| 114 | 121 | assertThat(passwordEncoder.matches("666666", captor.getValue().getSPasswordHash())).isTrue(); |
| 115 | 122 | } |
| 123 | + | |
| 124 | + @Test | |
| 125 | + @SuppressWarnings("unchecked") | |
| 126 | + void createUser_duplicateUserName_throws40002() { | |
| 127 | + stubConverterReturnsEmptyUser(); | |
| 128 | + // 第一次 selectCount(对 sUserName) 返回 > 0 → 触发 40002 | |
| 129 | + when(userMapper.selectCount(any(Wrapper.class))).thenReturn(1L); | |
| 130 | + | |
| 131 | + assertThatThrownBy(() -> service.createUser(baseDTO())) | |
| 132 | + .isInstanceOf(BusinessException.class) | |
| 133 | + .matches(e -> ((BusinessException) e).getCode() == 40002); | |
| 134 | + | |
| 135 | + verify(userMapper, never()).insert(any(User.class)); | |
| 136 | + } | |
| 137 | + | |
| 138 | + @Test | |
| 139 | + @SuppressWarnings("unchecked") | |
| 140 | + void createUser_duplicateUserCode_throws40003() { | |
| 141 | + stubConverterReturnsEmptyUser(); | |
| 142 | + // 第一次 selectCount(userName)=0,第二次(userCode)=1 | |
| 143 | + when(userMapper.selectCount(any(Wrapper.class))) | |
| 144 | + .thenReturn(0L) | |
| 145 | + .thenReturn(1L); | |
| 146 | + | |
| 147 | + assertThatThrownBy(() -> service.createUser(baseDTO())) | |
| 148 | + .isInstanceOf(BusinessException.class) | |
| 149 | + .matches(e -> ((BusinessException) e).getCode() == 40003); | |
| 150 | + | |
| 151 | + verify(userMapper, never()).insert(any(User.class)); | |
| 152 | + } | |
| 116 | 153 | } | ... | ... |