浏览代码

完善 AdminAuthServiceImpl 单元测试

YunaiV 2 年之前
父节点
当前提交
ba78d9964a

+ 8 - 8
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 {
     @Override
     public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
         // 校验验证码
-        verifyCaptcha(reqVO);
+        validateCaptcha(reqVO);
 
         // 使用账号密码,进行登录
         AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
@@ -171,14 +171,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
     }
 
-    @Override
-    public AuthLoginRespVO refreshToken(String refreshToken) {
-        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
-        return AuthConvert.INSTANCE.convert(accessTokenDO);
-    }
-
     @VisibleForTesting
-    void verifyCaptcha(AuthLoginReqVO reqVO) {
+    void validateCaptcha(AuthLoginReqVO reqVO) {
         // 如果验证码关闭,则不进行校验
         if (!captchaEnable) {
             return;
@@ -206,6 +200,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
         return AuthConvert.INSTANCE.convert(accessTokenDO);
     }
 
+    @Override
+    public AuthLoginRespVO refreshToken(String refreshToken) {
+        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
+        return AuthConvert.INSTANCE.convert(accessTokenDO);
+    }
+
     @Override
     public void logout(String token, Integer logType) {
         // 删除访问令牌

+ 1 - 0
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.*;
 
 /**
  * 后台用户 Service 实现类
+ *
  * @author 芋道源码
  */
 @Service("adminUserService")

+ 215 - 82
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java

@@ -1,31 +1,43 @@
 package cn.iocoder.yudao.module.system.service.auth;
 
+import cn.hutool.core.util.ReflectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
+import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
+import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
+import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
 import cn.iocoder.yudao.module.system.service.member.MemberService;
 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import com.xingyuv.captcha.model.common.ResponseModel;
 import com.xingyuv.captcha.service.CaptchaService;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 
 import javax.annotation.Resource;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validation;
 import javax.validation.Validator;
 
+import static cn.hutool.core.util.RandomUtil.randomEle;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.*;
 
@@ -42,17 +54,24 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
     @MockBean
     private LoginLogService loginLogService;
     @MockBean
-    private SocialUserService socialService;
+    private SocialUserService socialUserService;
     @MockBean
     private SmsCodeApi smsCodeApi;
     @MockBean
     private OAuth2TokenService oauth2TokenService;
     @MockBean
     private MemberService memberService;
-
     @MockBean
     private Validator validator;
 
+    @BeforeEach
+    public void setUp() {
+        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
+        // 注入一个 Validator 对象
+        ReflectUtil.setFieldValue(authService, "validator",
+                Validation.buildDefaultValidatorFactory().getValidator());
+    }
+
     @Test
     public void testAuthenticate_success() {
         // 准备参数
@@ -78,7 +97,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
         String password = randomString();
 
         // 调用, 并断言异常
-        AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
+        assertServiceException(() -> authService.authenticate(username, password),
                 AUTH_LOGIN_BAD_CREDENTIALS);
         verify(loginLogService).createLoginLog(
                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
@@ -98,7 +117,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
         when(userService.getUserByUsername(eq(username))).thenReturn(user);
 
         // 调用, 并断言异常
-        AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
+        assertServiceException(() -> authService.authenticate(username, password),
                 AUTH_LOGIN_BAD_CREDENTIALS);
         verify(loginLogService).createLoginLog(
                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
@@ -120,7 +139,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
         when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true);
 
         // 调用, 并断言异常
-        AssertUtils.assertServiceException(() -> authService.authenticate(username, password),
+        assertServiceException(() -> authService.authenticate(username, password),
                 AUTH_LOGIN_USER_DISABLED);
         verify(loginLogService).createLoginLog(
                 argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
@@ -129,82 +148,194 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
         );
     }
 
-//    @Test
-//    public void testCaptcha_success() {
-//        // 准备参数
-//        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-//
-//        // mock 验证码正确
-//        when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
-//
-//        // 调用
-//        authService.verifyCaptcha(reqVO);
-//        // 断言
-//        verify(captchaService).deleteCaptchaCode(reqVO.getUuid());
-//    }
-//
-//    @Test
-//    public void testCaptcha_notFound() {
-//        // 准备参数
-//        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-//
-//        // 调用, 并断言异常
-//        assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_NOT_FOUND);
-//        // 校验调用参数
-//        verify(loginLogService, times(1)).createLoginLog(
-//            argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-//                    && o.getResult().equals(LoginResultEnum.CAPTCHA_NOT_FOUND.getResult()))
-//        );
-//    }
-
-//    @Test
-//    public void testCaptcha_codeError() {
-//        // 准备参数
-//        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-//
-//        // mock 验证码不正确
-//        String code = randomString();
-//        when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(code);
-//
-//        // 调用, 并断言异常
-//        assertServiceException(() -> authService.verifyCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR);
-//        // 校验调用参数
-//        verify(loginLogService).createLoginLog(
-//            argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-//                    && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
-//        );
-//    }
-
-//    @Test
-//    public void testLogin_success() {
-//        // 准备参数
-//        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
-//                o.setUsername("test_username").setPassword("test_password"));
-//
-//        // mock 验证码正确
-//        when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
-//        // mock user 数据
-//        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
-//                .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
-//        when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
-//        // mock password 匹配
-//        when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
-//        // mock 缓存登录用户到 Redis
-//        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
-//                .setUserType(UserTypeEnum.ADMIN.getValue()));
-//        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
-//                .thenReturn(accessTokenDO);
-//
-//        // 调用, 并断言异常
-//        AuthLoginRespVO loginRespVO = authService.login(reqVO);
-//        assertPojoEquals(accessTokenDO, loginRespVO);
-//        // 校验调用参数
-//        verify(loginLogService).createLoginLog(
-//            argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-//                    && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
-//                    && o.getUserId().equals(user.getId()))
-//        );
-//    }
+        @Test
+    public void testLogin_success() {
+        // 准备参数
+        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
+                o.setUsername("test_username").setPassword("test_password")
+                        .setSocialType(randomEle(SocialTypeEnum.values()).getType()));
+
+        // mock 验证码正确
+        ReflectUtil.setFieldValue(authService, "captchaEnable", false);
+        // mock user 数据
+        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
+                .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
+        when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
+        // mock password 匹配
+        when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
+        // mock 缓存登录用户到 Redis
+        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
+                .setUserType(UserTypeEnum.ADMIN.getValue()));
+        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
+                .thenReturn(accessTokenDO);
+
+        // 调用,并校验
+        AuthLoginRespVO loginRespVO = authService.login(reqVO);
+        assertPojoEquals(accessTokenDO, loginRespVO);
+        // 校验调用参数
+        verify(loginLogService).createLoginLog(
+            argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
+                    && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
+                    && o.getUserId().equals(user.getId()))
+        );
+        verify(socialUserService).bindSocialUser(eq(new SocialUserBindReqDTO(
+                user.getId(), UserTypeEnum.ADMIN.getValue(),
+                reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())));
+    }
+
+    @Test
+    public void testSendSmsCode() {
+        // 准备参数
+        String mobile = randomString();
+        Integer scene = randomEle(SmsSceneEnum.values()).getScene();
+        AuthSmsSendReqVO reqVO = new AuthSmsSendReqVO(mobile, scene);
+        // mock 方法(用户信息)
+        AdminUserDO user = randomPojo(AdminUserDO.class);
+        when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
+
+        // 调用
+        authService.sendSmsCode(reqVO);
+        // 断言
+        verify(smsCodeApi).sendSmsCode(argThat(sendReqDTO -> {
+            assertEquals(mobile, sendReqDTO.getMobile());
+            assertEquals(scene, sendReqDTO.getScene());
+            return true;
+        }));
+    }
+
+    @Test
+    public void testSmsLogin_success() {
+        // 准备参数
+        String mobile = randomString();
+        String scene = randomString();
+        AuthSmsLoginReqVO reqVO = new AuthSmsLoginReqVO(mobile, scene);
+        // mock 方法(用户信息)
+        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L));
+        when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
+        // mock 缓存登录用户到 Redis
+        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
+                .setUserType(UserTypeEnum.ADMIN.getValue()));
+        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
+                .thenReturn(accessTokenDO);
+
+        // 调用,并断言
+        AuthLoginRespVO loginRespVO = authService.smsLogin(reqVO);
+        assertPojoEquals(accessTokenDO, loginRespVO);
+        // 断言调用
+        verify(loginLogService).createLoginLog(
+                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_MOBILE.getType())
+                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
+                        && o.getUserId().equals(user.getId()))
+        );
+    }
+
+    @Test
+    public void testSocialLogin_success() {
+        // 准备参数
+        AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class);
+        // mock 方法(绑定的用户编号)
+        Long userId = 1L;
+        when(socialUserService.getBindUserId(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
+                eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(userId);
+        // mock(用户)
+        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
+        when(userService.getUser(eq(userId))).thenReturn(user);
+        // mock 缓存登录用户到 Redis
+        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
+                .setUserType(UserTypeEnum.ADMIN.getValue()));
+        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
+                .thenReturn(accessTokenDO);
+
+        // 调用,并断言
+        AuthLoginRespVO loginRespVO = authService.socialLogin(reqVO);
+        assertPojoEquals(accessTokenDO, loginRespVO);
+        // 断言调用
+        verify(loginLogService).createLoginLog(
+                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_SOCIAL.getType())
+                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
+                        && o.getUserId().equals(user.getId()))
+        );
+    }
+
+    @Test
+    public void testValidateCaptcha_successWithEnable() {
+        // 准备参数
+        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
+
+        // mock 验证码打开
+        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
+        // mock 验证通过
+        when(captchaService.verification(argThat(captchaVO -> {
+            assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
+            return true;
+        }))).thenReturn(ResponseModel.success());
+
+        // 调用,无需断言
+        authService.validateCaptcha(reqVO);
+    }
+
+    @Test
+    public void testValidateCaptcha_successWithDisable() {
+        // 准备参数
+        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
+
+        // mock 验证码关闭
+        ReflectUtil.setFieldValue(authService, "captchaEnable", false);
+
+        // 调用,无需断言
+        authService.validateCaptcha(reqVO);
+    }
+
+    @Test
+    public void testValidateCaptcha_constraintViolationException() {
+        // 准备参数
+        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class).setCaptchaVerification(null);
+
+        // mock 验证码打开
+        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
+
+        // 调用,并断言异常
+        assertThrows(ConstraintViolationException.class, () -> authService.validateCaptcha(reqVO),
+                "验证码不能为空");
+    }
+
+
+    @Test
+    public void testCaptcha_fail() {
+        // 准备参数
+        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
+
+        // mock 验证码打开
+        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
+        // mock 验证通过
+        when(captchaService.verification(argThat(captchaVO -> {
+            assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
+            return true;
+        }))).thenReturn(ResponseModel.errorMsg("就是不对"));
+
+        // 调用, 并断言异常
+        assertServiceException(() -> authService.validateCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR, "就是不对");
+        // 校验调用参数
+        verify(loginLogService).createLoginLog(
+            argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
+                    && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
+        );
+    }
+
+    @Test
+    public void testRefreshToken() {
+        // 准备参数
+        String refreshToken = randomString();
+        // mock 方法
+        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
+        when(oauth2TokenService.refreshAccessToken(eq(refreshToken), eq("default")))
+                .thenReturn(accessTokenDO);
+
+        // 调用
+        AuthLoginRespVO loginRespVO = authService.refreshToken(refreshToken);
+        // 断言
+        assertPojoEquals(accessTokenDO, loginRespVO);
+    }
 
     @Test
     public void testLogout_success() {
@@ -221,6 +352,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
         verify(loginLogService).createLoginLog(argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType())
                     && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()))
         );
+        // 调用,并校验
+
     }
 
     @Test