Commit ba78d9964ab7423b8f424de67ae6d7537ba25285

Authored by YunaiV
1 parent e9814b12

完善 AdminAuthServiceImpl 单元测试

yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
... ... @@ -94,7 +94,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
94 94 @Override
95 95 public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
96 96 // 校验验证码
97   - verifyCaptcha(reqVO);
  97 + validateCaptcha(reqVO);
98 98  
99 99 // 使用账号密码,进行登录
100 100 AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
... ... @@ -171,14 +171,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
171 171 return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
172 172 }
173 173  
174   - @Override
175   - public AuthLoginRespVO refreshToken(String refreshToken) {
176   - OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
177   - return AuthConvert.INSTANCE.convert(accessTokenDO);
178   - }
179   -
180 174 @VisibleForTesting
181   - void verifyCaptcha(AuthLoginReqVO reqVO) {
  175 + void validateCaptcha(AuthLoginReqVO reqVO) {
182 176 // 如果验证码关闭,则不进行校验
183 177 if (!captchaEnable) {
184 178 return;
... ... @@ -207,6 +201,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
207 201 }
208 202  
209 203 @Override
  204 + public AuthLoginRespVO refreshToken(String refreshToken) {
  205 + OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
  206 + return AuthConvert.INSTANCE.convert(accessTokenDO);
  207 + }
  208 +
  209 + @Override
210 210 public void logout(String token, Integer logType) {
211 211 // 删除访问令牌
212 212 OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(token);
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
... ... @@ -43,6 +43,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
43 43  
44 44 /**
45 45 * 后台用户 Service 实现类
  46 + *
46 47 * @author 芋道源码
47 48 */
48 49 @Service("adminUserService")
... ...
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
1 1 package cn.iocoder.yudao.module.system.service.auth;
2 2  
  3 +import cn.hutool.core.util.ReflectUtil;
3 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
6   -import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
7 7 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
  8 +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  9 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
8 10 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
9 11 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
10 12 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
11 13 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
  14 +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
  15 +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
12 16 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
13 17 import cn.iocoder.yudao.module.system.service.member.MemberService;
14 18 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
15 19 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
16 20 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
  21 +import com.xingyuv.captcha.model.common.ResponseModel;
17 22 import com.xingyuv.captcha.service.CaptchaService;
  23 +import org.junit.jupiter.api.BeforeEach;
18 24 import org.junit.jupiter.api.Test;
19 25 import org.springframework.boot.test.mock.mockito.MockBean;
20 26 import org.springframework.context.annotation.Import;
21 27  
22 28 import javax.annotation.Resource;
  29 +import javax.validation.ConstraintViolationException;
  30 +import javax.validation.Validation;
23 31 import javax.validation.Validator;
24 32  
  33 +import static cn.hutool.core.util.RandomUtil.randomEle;
25 34 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  35 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
26 36 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
27 37 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
28 38 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
  39 +import static org.junit.jupiter.api.Assertions.assertEquals;
  40 +import static org.junit.jupiter.api.Assertions.assertThrows;
29 41 import static org.mockito.ArgumentMatchers.eq;
30 42 import static org.mockito.Mockito.*;
31 43  
... ... @@ -42,17 +54,24 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
42 54 @MockBean
43 55 private LoginLogService loginLogService;
44 56 @MockBean
45   - private SocialUserService socialService;
  57 + private SocialUserService socialUserService;
46 58 @MockBean
47 59 private SmsCodeApi smsCodeApi;
48 60 @MockBean
49 61 private OAuth2TokenService oauth2TokenService;
50 62 @MockBean
51 63 private MemberService memberService;
52   -
53 64 @MockBean
54 65 private Validator validator;
55 66  
  67 + @BeforeEach
  68 + public void setUp() {
  69 + ReflectUtil.setFieldValue(authService, "captchaEnable", true);
  70 + // 注入一个 Validator 对象
  71 + ReflectUtil.setFieldValue(authService, "validator",
  72 + Validation.buildDefaultValidatorFactory().getValidator());
  73 + }
  74 +
56 75 @Test
57 76 public void testAuthenticate_success() {
58 77 // 准备参数
... ... @@ -78,7 +97,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
78 97 String password = randomString();
79 98  
80 99 // 调用, 并断言异常
81   - AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
  100 + assertServiceException(() -> authService.authenticate(username, password),
82 101 AUTH_LOGIN_BAD_CREDENTIALS);
83 102 verify(loginLogService).createLoginLog(
84 103 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
... ... @@ -98,7 +117,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
98 117 when(userService.getUserByUsername(eq(username))).thenReturn(user);
99 118  
100 119 // 调用, 并断言异常
101   - AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
  120 + assertServiceException(() -> authService.authenticate(username, password),
102 121 AUTH_LOGIN_BAD_CREDENTIALS);
103 122 verify(loginLogService).createLoginLog(
104 123 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
... ... @@ -120,7 +139,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
120 139 when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true);
121 140  
122 141 // 调用, 并断言异常
123   - AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
  142 + assertServiceException(() -> authService.authenticate(username, password),
124 143 AUTH_LOGIN_USER_DISABLED);
125 144 verify(loginLogService).createLoginLog(
126 145 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
... ... @@ -129,82 +148,194 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
129 148 );
130 149 }
131 150  
132   -// @Test
133   -// public void testCaptcha_success() {
134   -// // 准备参数
135   -// AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
136   -//
137   -// // mock 验证码正确
138   -// when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
139   -//
140   -// // 调用
141   -// authService.verifyCaptcha(reqVO);
142   -// // 断言
143   -// verify(captchaService).deleteCaptchaCode(reqVO.getUuid());
144   -// }
145   -//
146   -// @Test
147   -// public void testCaptcha_notFound() {
148   -// // 准备参数
149   -// AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
150   -//
151   -// // 调用, 并断言异常
152   -// assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_NOT_FOUND);
153   -// // 校验调用参数
154   -// verify(loginLogService, times(1)).createLoginLog(
155   -// argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
156   -// && o.getResult().equals(LoginResultEnum.CAPTCHA_NOT_FOUND.getResult()))
157   -// );
158   -// }
159   -
160   -// @Test
161   -// public void testCaptcha_codeError() {
162   -// // 准备参数
163   -// AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
164   -//
165   -// // mock 验证码不正确
166   -// String code = randomString();
167   -// when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(code);
168   -//
169   -// // 调用, 并断言异常
170   -// assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR);
171   -// // 校验调用参数
172   -// verify(loginLogService).createLoginLog(
173   -// argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
174   -// && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
175   -// );
176   -// }
177   -
178   -// @Test
179   -// public void testLogin_success() {
180   -// // 准备参数
181   -// AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
182   -// o.setUsername("test_username").setPassword("test_password"));
183   -//
184   -// // mock 验证码正确
185   -// when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
186   -// // mock user 数据
187   -// AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
188   -// .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
189   -// when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
190   -// // mock password 匹配
191   -// when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
192   -// // mock 缓存登录用户到 Redis
193   -// OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
194   -// .setUserType(UserTypeEnum.ADMIN.getValue()));
195   -// when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
196   -// .thenReturn(accessTokenDO);
197   -//
198   -// // 调用, 并断言异常
199   -// AuthLoginRespVO loginRespVO = authService.login(reqVO);
200   -// assertPojoEquals(accessTokenDO, loginRespVO);
201   -// // 校验调用参数
202   -// verify(loginLogService).createLoginLog(
203   -// argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
204   -// && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
205   -// && o.getUserId().equals(user.getId()))
206   -// );
207   -// }
  151 + @Test
  152 + public void testLogin_success() {
  153 + // 准备参数
  154 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
  155 + o.setUsername("test_username").setPassword("test_password")
  156 + .setSocialType(randomEle(SocialTypeEnum.values()).getType()));
  157 +
  158 + // mock 验证码正确
  159 + ReflectUtil.setFieldValue(authService, "captchaEnable", false);
  160 + // mock user 数据
  161 + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
  162 + .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
  163 + when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
  164 + // mock password 匹配
  165 + when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
  166 + // mock 缓存登录用户到 Redis
  167 + OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
  168 + .setUserType(UserTypeEnum.ADMIN.getValue()));
  169 + when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
  170 + .thenReturn(accessTokenDO);
  171 +
  172 + // 调用,并校验
  173 + AuthLoginRespVO loginRespVO = authService.login(reqVO);
  174 + assertPojoEquals(accessTokenDO, loginRespVO);
  175 + // 校验调用参数
  176 + verify(loginLogService).createLoginLog(
  177 + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
  178 + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
  179 + && o.getUserId().equals(user.getId()))
  180 + );
  181 + verify(socialUserService).bindSocialUser(eq(new SocialUserBindReqDTO(
  182 + user.getId(), UserTypeEnum.ADMIN.getValue(),
  183 + reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())));
  184 + }
  185 +
  186 + @Test
  187 + public void testSendSmsCode() {
  188 + // 准备参数
  189 + String mobile = randomString();
  190 + Integer scene = randomEle(SmsSceneEnum.values()).getScene();
  191 + AuthSmsSendReqVO reqVO = new AuthSmsSendReqVO(mobile, scene);
  192 + // mock 方法(用户信息)
  193 + AdminUserDO user = randomPojo(AdminUserDO.class);
  194 + when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
  195 +
  196 + // 调用
  197 + authService.sendSmsCode(reqVO);
  198 + // 断言
  199 + verify(smsCodeApi).sendSmsCode(argThat(sendReqDTO -> {
  200 + assertEquals(mobile, sendReqDTO.getMobile());
  201 + assertEquals(scene, sendReqDTO.getScene());
  202 + return true;
  203 + }));
  204 + }
  205 +
  206 + @Test
  207 + public void testSmsLogin_success() {
  208 + // 准备参数
  209 + String mobile = randomString();
  210 + String scene = randomString();
  211 + AuthSmsLoginReqVO reqVO = new AuthSmsLoginReqVO(mobile, scene);
  212 + // mock 方法(用户信息)
  213 + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L));
  214 + when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
  215 + // mock 缓存登录用户到 Redis
  216 + OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
  217 + .setUserType(UserTypeEnum.ADMIN.getValue()));
  218 + when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
  219 + .thenReturn(accessTokenDO);
  220 +
  221 + // 调用,并断言
  222 + AuthLoginRespVO loginRespVO = authService.smsLogin(reqVO);
  223 + assertPojoEquals(accessTokenDO, loginRespVO);
  224 + // 断言调用
  225 + verify(loginLogService).createLoginLog(
  226 + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_MOBILE.getType())
  227 + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
  228 + && o.getUserId().equals(user.getId()))
  229 + );
  230 + }
  231 +
  232 + @Test
  233 + public void testSocialLogin_success() {
  234 + // 准备参数
  235 + AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class);
  236 + // mock 方法(绑定的用户编号)
  237 + Long userId = 1L;
  238 + when(socialUserService.getBindUserId(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
  239 + eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(userId);
  240 + // mock(用户)
  241 + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
  242 + when(userService.getUser(eq(userId))).thenReturn(user);
  243 + // mock 缓存登录用户到 Redis
  244 + OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
  245 + .setUserType(UserTypeEnum.ADMIN.getValue()));
  246 + when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
  247 + .thenReturn(accessTokenDO);
  248 +
  249 + // 调用,并断言
  250 + AuthLoginRespVO loginRespVO = authService.socialLogin(reqVO);
  251 + assertPojoEquals(accessTokenDO, loginRespVO);
  252 + // 断言调用
  253 + verify(loginLogService).createLoginLog(
  254 + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_SOCIAL.getType())
  255 + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
  256 + && o.getUserId().equals(user.getId()))
  257 + );
  258 + }
  259 +
  260 + @Test
  261 + public void testValidateCaptcha_successWithEnable() {
  262 + // 准备参数
  263 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
  264 +
  265 + // mock 验证码打开
  266 + ReflectUtil.setFieldValue(authService, "captchaEnable", true);
  267 + // mock 验证通过
  268 + when(captchaService.verification(argThat(captchaVO -> {
  269 + assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
  270 + return true;
  271 + }))).thenReturn(ResponseModel.success());
  272 +
  273 + // 调用,无需断言
  274 + authService.validateCaptcha(reqVO);
  275 + }
  276 +
  277 + @Test
  278 + public void testValidateCaptcha_successWithDisable() {
  279 + // 准备参数
  280 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
  281 +
  282 + // mock 验证码关闭
  283 + ReflectUtil.setFieldValue(authService, "captchaEnable", false);
  284 +
  285 + // 调用,无需断言
  286 + authService.validateCaptcha(reqVO);
  287 + }
  288 +
  289 + @Test
  290 + public void testValidateCaptcha_constraintViolationException() {
  291 + // 准备参数
  292 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class).setCaptchaVerification(null);
  293 +
  294 + // mock 验证码打开
  295 + ReflectUtil.setFieldValue(authService, "captchaEnable", true);
  296 +
  297 + // 调用,并断言异常
  298 + assertThrows(ConstraintViolationException.class, () -> authService.validateCaptcha(reqVO),
  299 + "验证码不能为空");
  300 + }
  301 +
  302 +
  303 + @Test
  304 + public void testCaptcha_fail() {
  305 + // 准备参数
  306 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
  307 +
  308 + // mock 验证码打开
  309 + ReflectUtil.setFieldValue(authService, "captchaEnable", true);
  310 + // mock 验证通过
  311 + when(captchaService.verification(argThat(captchaVO -> {
  312 + assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
  313 + return true;
  314 + }))).thenReturn(ResponseModel.errorMsg("就是不对"));
  315 +
  316 + // 调用, 并断言异常
  317 + assertServiceException(() -> authService.validateCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR, "就是不对");
  318 + // 校验调用参数
  319 + verify(loginLogService).createLoginLog(
  320 + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
  321 + && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
  322 + );
  323 + }
  324 +
  325 + @Test
  326 + public void testRefreshToken() {
  327 + // 准备参数
  328 + String refreshToken = randomString();
  329 + // mock 方法
  330 + OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
  331 + when(oauth2TokenService.refreshAccessToken(eq(refreshToken), eq("default")))
  332 + .thenReturn(accessTokenDO);
  333 +
  334 + // 调用
  335 + AuthLoginRespVO loginRespVO = authService.refreshToken(refreshToken);
  336 + // 断言
  337 + assertPojoEquals(accessTokenDO, loginRespVO);
  338 + }
208 339  
209 340 @Test
210 341 public void testLogout_success() {
... ... @@ -221,6 +352,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
221 352 verify(loginLogService).createLoginLog(argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType())
222 353 && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()))
223 354 );
  355 + // 调用,并校验
  356 +
224 357 }
225 358  
226 359 @Test
... ...