Commit c2e9ecf7be47d207464183a5f26e7d81efa5bf5b

Authored by YunaiV
1 parent f6568889

✅ 增加 social 模块的单测覆盖率

yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserPageReqVO.java
@@ -23,7 +23,7 @@ public class SocialUserPageReqVO extends PageParam { @@ -23,7 +23,7 @@ public class SocialUserPageReqVO extends PageParam {
23 @Schema(description = "用户昵称", example = "李四") 23 @Schema(description = "用户昵称", example = "李四")
24 private String nickname; 24 private String nickname;
25 25
26 - @Schema(description = "社交 openid", example = "oz-Jdt0kd_jdhUxJHQdBJMlOFN7w\n") 26 + @Schema(description = "社交 openid", example = "oz-Jdt0kd_jdhUxJHQdBJMlOFN7w")
27 private String openid; 27 private String openid;
28 28
29 @Schema(description = "创建时间") 29 @Schema(description = "创建时间")
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java
@@ -142,7 +142,8 @@ public class SocialClientServiceImpl implements SocialClientService { @@ -142,7 +142,8 @@ public class SocialClientServiceImpl implements SocialClientService {
142 * @param userType 用户类型 142 * @param userType 用户类型
143 * @return AuthRequest 对象 143 * @return AuthRequest 对象
144 */ 144 */
145 - private AuthRequest buildAuthRequest(Integer socialType, Integer userType) { 145 + @VisibleForTesting
  146 + AuthRequest buildAuthRequest(Integer socialType, Integer userType) {
146 // 1. 先查找默认的配置项,从 application-*.yaml 中读取 147 // 1. 先查找默认的配置项,从 application-*.yaml 中读取
147 AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource()); 148 AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource());
148 Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType)); 149 Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType));
@@ -180,7 +181,8 @@ public class SocialClientServiceImpl implements SocialClientService { @@ -180,7 +181,8 @@ public class SocialClientServiceImpl implements SocialClientService {
180 * @param userType 用户类型 181 * @param userType 用户类型
181 * @return WxMpService 对象 182 * @return WxMpService 对象
182 */ 183 */
183 - private WxMpService getWxMpService(Integer userType) { 184 + @VisibleForTesting
  185 + WxMpService getWxMpService(Integer userType) {
184 // 第一步,查询 DB 的配置项,获得对应的 WxMpService 对象 186 // 第一步,查询 DB 的配置项,获得对应的 WxMpService 对象
185 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType( 187 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
186 SocialTypeEnum.WECHAT_MP.getType(), userType); 188 SocialTypeEnum.WECHAT_MP.getType(), userType);
@@ -198,7 +200,7 @@ public class SocialClientServiceImpl implements SocialClientService { @@ -198,7 +200,7 @@ public class SocialClientServiceImpl implements SocialClientService {
198 * @param clientSecret 微信公众号 secret 200 * @param clientSecret 微信公众号 secret
199 * @return WxMpService 对象 201 * @return WxMpService 对象
200 */ 202 */
201 - private WxMpService buildWxMpService(String clientId, String clientSecret) { 203 + public WxMpService buildWxMpService(String clientId, String clientSecret) {
202 // 第一步,创建 WxMpRedisConfigImpl 对象 204 // 第一步,创建 WxMpRedisConfigImpl 对象
203 WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl( 205 WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl(
204 new RedisTemplateWxRedisOps(stringRedisTemplate), 206 new RedisTemplateWxRedisOps(stringRedisTemplate),
@@ -231,7 +233,8 @@ public class SocialClientServiceImpl implements SocialClientService { @@ -231,7 +233,8 @@ public class SocialClientServiceImpl implements SocialClientService {
231 * @param userType 用户类型 233 * @param userType 用户类型
232 * @return WxMpService 对象 234 * @return WxMpService 对象
233 */ 235 */
234 - private WxMaService getWxMaService(Integer userType) { 236 + @VisibleForTesting
  237 + WxMaService getWxMaService(Integer userType) {
235 // 第一步,查询 DB 的配置项,获得对应的 WxMaService 对象 238 // 第一步,查询 DB 的配置项,获得对应的 WxMaService 对象
236 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType( 239 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
237 SocialTypeEnum.WECHAT_MINI_APP.getType(), userType); 240 SocialTypeEnum.WECHAT_MINI_APP.getType(), userType);
@@ -311,7 +314,6 @@ public class SocialClientServiceImpl implements SocialClientService { @@ -311,7 +314,6 @@ public class SocialClientServiceImpl implements SocialClientService {
311 * @param userType 用户类型 314 * @param userType 用户类型
312 * @param socialType 社交类型 315 * @param socialType 社交类型
313 */ 316 */
314 - @VisibleForTesting  
315 private void validateSocialClientUnique(Long id, Integer userType, Integer socialType) { 317 private void validateSocialClientUnique(Long id, Integer userType, Integer socialType) {
316 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType( 318 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
317 socialType, userType); 319 socialType, userType);
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.collection.ListUtil;  
5 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
6 import cn.iocoder.yudao.framework.common.exception.ServiceException; 5 import cn.iocoder.yudao.framework.common.exception.ServiceException;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
9 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; 8 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
10 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; 9 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
11 -import cn.iocoder.yudao.module.system.convert.social.SocialUserConvert;  
12 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; 10 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
13 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 11 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
14 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; 12 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
@@ -22,14 +20,14 @@ import org.springframework.validation.annotation.Validated; @@ -22,14 +20,14 @@ import org.springframework.validation.annotation.Validated;
22 20
23 import javax.annotation.Resource; 21 import javax.annotation.Resource;
24 import javax.validation.constraints.NotNull; 22 import javax.validation.constraints.NotNull;
25 -import java.util.Collection;  
26 import java.util.Collections; 23 import java.util.Collections;
27 import java.util.List; 24 import java.util.List;
28 25
29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
30 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 27 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
31 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 28 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
32 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; 29 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND;
  30 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
33 31
34 /** 32 /**
35 * 社交用户 Service 实现类 33 * 社交用户 Service 实现类
@@ -61,7 +59,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -61,7 +59,7 @@ public class SocialUserServiceImpl implements SocialUserService {
61 } 59 }
62 60
63 @Override 61 @Override
64 - @Transactional 62 + @Transactional(rollbackFor = Exception.class)
65 public String bindSocialUser(SocialUserBindReqDTO reqDTO) { 63 public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
66 // 获得社交用户 64 // 获得社交用户
67 SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(), 65 SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
@@ -110,7 +108,6 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -110,7 +108,6 @@ public class SocialUserServiceImpl implements SocialUserService {
110 return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId()); 108 return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId());
111 } 109 }
112 110
113 - // TODO 芋艿:调整下单测  
114 /** 111 /**
115 * 授权获得对应的社交用户 112 * 授权获得对应的社交用户
116 * 如果授权失败,则会抛出 {@link ServiceException} 异常 113 * 如果授权失败,则会抛出 {@link ServiceException} 异常
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
  3 +import cn.binarywang.wx.miniapp.api.WxMaService;
  4 +import cn.binarywang.wx.miniapp.api.WxMaUserService;
  5 +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
  6 +import cn.hutool.core.util.ReflectUtil;
  7 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  8 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 10 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; 11 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
6 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; 12 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
7 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; 13 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
8 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper; 14 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper;
9 -import org.junit.jupiter.api.Disabled; 15 +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
  16 +import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
  17 +import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
  18 +import com.xingyuv.jushauth.config.AuthConfig;
  19 +import com.xingyuv.jushauth.model.AuthResponse;
  20 +import com.xingyuv.jushauth.model.AuthUser;
  21 +import com.xingyuv.jushauth.request.AuthDefaultRequest;
  22 +import com.xingyuv.jushauth.request.AuthRequest;
  23 +import com.xingyuv.jushauth.utils.AuthStateUtils;
  24 +import com.xingyuv.justauth.AuthRequestFactory;
  25 +import me.chanjar.weixin.common.bean.WxJsapiSignature;
  26 +import me.chanjar.weixin.common.error.WxErrorException;
  27 +import me.chanjar.weixin.mp.api.WxMpService;
10 import org.junit.jupiter.api.Test; 28 import org.junit.jupiter.api.Test;
  29 +import org.mockito.MockedStatic;
  30 +import org.springframework.boot.test.mock.mockito.MockBean;
11 import org.springframework.context.annotation.Import; 31 import org.springframework.context.annotation.Import;
  32 +import org.springframework.data.redis.core.StringRedisTemplate;
12 33
13 import javax.annotation.Resource; 34 import javax.annotation.Resource;
14 35
  36 +import static cn.hutool.core.util.RandomUtil.randomEle;
15 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; 37 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
16 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 38 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
17 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 39 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
18 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;  
19 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
20 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_CLIENT_NOT_EXISTS; 40 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  41 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
21 import static org.junit.jupiter.api.Assertions.*; 42 import static org.junit.jupiter.api.Assertions.*;
  43 +import static org.mockito.Mockito.*;
22 44
23 -// TODO 芋艿:单测后续补充下;  
24 /** 45 /**
25 * {@link SocialClientServiceImpl} 的单元测试类 46 * {@link SocialClientServiceImpl} 的单元测试类
26 * 47 *
27 * @author 芋道源码 48 * @author 芋道源码
28 */ 49 */
29 @Import(SocialClientServiceImpl.class) 50 @Import(SocialClientServiceImpl.class)
30 -@Disabled  
31 public class SocialClientServiceImplTest extends BaseDbUnitTest { 51 public class SocialClientServiceImplTest extends BaseDbUnitTest {
32 52
33 @Resource 53 @Resource
@@ -36,10 +56,305 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest { @@ -36,10 +56,305 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest {
36 @Resource 56 @Resource
37 private SocialClientMapper socialClientMapper; 57 private SocialClientMapper socialClientMapper;
38 58
  59 + @MockBean
  60 + private AuthRequestFactory authRequestFactory;
  61 +
  62 + @MockBean
  63 + private WxMpService wxMpService;
  64 + @MockBean
  65 + private WxMpProperties wxMpProperties;
  66 + @MockBean
  67 + private StringRedisTemplate stringRedisTemplate;
  68 + @MockBean
  69 + private WxMaService wxMaService;
  70 + @MockBean
  71 + private WxMaProperties wxMaProperties;
  72 +
  73 + @Test
  74 + public void testGetAuthorizeUrl() {
  75 + try (MockedStatic<AuthStateUtils> authStateUtilsMock = mockStatic(AuthStateUtils.class)) {
  76 + // 准备参数
  77 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  78 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  79 + String redirectUri = "sss";
  80 + // mock 获得对应的 AuthRequest 实现
  81 + AuthRequest authRequest = mock(AuthRequest.class);
  82 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  83 + // mock 方法
  84 + authStateUtilsMock.when(AuthStateUtils::createState).thenReturn("aoteman");
  85 + when(authRequest.authorize(eq("aoteman"))).thenReturn("https://www.iocoder.cn?redirect_uri=yyy");
  86 +
  87 + // 调用
  88 + String url = socialClientService.getAuthorizeUrl(socialType, userType, redirectUri);
  89 + // 断言
  90 + assertEquals("https://www.iocoder.cn?redirect_uri=sss", url);
  91 + }
  92 + }
  93 +
  94 + @Test
  95 + public void testAuthSocialUser_success() {
  96 + // 准备参数
  97 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  98 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  99 + String code = randomString();
  100 + String state = randomString();
  101 + // mock 方法(AuthRequest)
  102 + AuthRequest authRequest = mock(AuthRequest.class);
  103 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  104 + // mock 方法(AuthResponse)
  105 + AuthUser authUser = randomPojo(AuthUser.class);
  106 + AuthResponse<?> authResponse = new AuthResponse<>(2000, null, authUser);
  107 + when(authRequest.login(argThat(authCallback -> {
  108 + assertEquals(code, authCallback.getCode());
  109 + assertEquals(state, authCallback.getState());
  110 + return true;
  111 + }))).thenReturn(authResponse);
  112 +
  113 + // 调用
  114 + AuthUser result = socialClientService.getAuthUser(socialType, userType, code, state);
  115 + // 断言
  116 + assertSame(authUser, result);
  117 + }
  118 +
  119 + @Test
  120 + public void testAuthSocialUser_fail() {
  121 + // 准备参数
  122 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  123 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  124 + String code = randomString();
  125 + String state = randomString();
  126 + // mock 方法(AuthRequest)
  127 + AuthRequest authRequest = mock(AuthRequest.class);
  128 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  129 + // mock 方法(AuthResponse)
  130 + AuthResponse<?> authResponse = new AuthResponse<>(0, "模拟失败", null);
  131 + when(authRequest.login(argThat(authCallback -> {
  132 + assertEquals(code, authCallback.getCode());
  133 + assertEquals(state, authCallback.getState());
  134 + return true;
  135 + }))).thenReturn(authResponse);
  136 +
  137 + // 调用并断言
  138 + assertServiceException(
  139 + () -> socialClientService.getAuthUser(socialType, userType, code, state),
  140 + SOCIAL_USER_AUTH_FAILURE, "模拟失败");
  141 + }
  142 +
  143 + @Test
  144 + public void testBuildAuthRequest_clientNull() {
  145 + // 准备参数
  146 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  147 + Integer userType = randomPojo(SocialTypeEnum.class).getType();
  148 + // mock 获得对应的 AuthRequest 实现
  149 + AuthRequest authRequest = mock(AuthDefaultRequest.class);
  150 + AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
  151 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  152 +
  153 + // 调用
  154 + AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
  155 + // 断言
  156 + assertSame(authRequest, result);
  157 + assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
  158 + }
  159 +
  160 + @Test
  161 + public void testBuildAuthRequest_clientDisable() {
  162 + // 准备参数
  163 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  164 + Integer userType = randomPojo(SocialTypeEnum.class).getType();
  165 + // mock 获得对应的 AuthRequest 实现
  166 + AuthRequest authRequest = mock(AuthDefaultRequest.class);
  167 + AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
  168 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  169 + // mock 数据
  170 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
  171 + .setUserType(userType).setSocialType(socialType));
  172 + socialClientMapper.insert(client);
  173 +
  174 + // 调用
  175 + AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
  176 + // 断言
  177 + assertSame(authRequest, result);
  178 + assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
  179 + }
  180 +
  181 + @Test
  182 + public void testBuildAuthRequest_clientEnable() {
  183 + // 准备参数
  184 + Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
  185 + Integer userType = randomPojo(SocialTypeEnum.class).getType();
  186 + // mock 获得对应的 AuthRequest 实现
  187 + AuthConfig authConfig = mock(AuthConfig.class);
  188 + AuthRequest authRequest = mock(AuthDefaultRequest.class);
  189 + ReflectUtil.setFieldValue(authRequest, "config", authConfig);
  190 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  191 + // mock 数据
  192 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  193 + .setUserType(userType).setSocialType(socialType));
  194 + socialClientMapper.insert(client);
  195 +
  196 + // 调用
  197 + AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
  198 + // 断言
  199 + assertSame(authRequest, result);
  200 + assertNotSame(authConfig, ReflectUtil.getFieldValue(authRequest, "config"));
  201 + }
  202 +
  203 + // =================== 微信公众号独有 ===================
  204 +
  205 + @Test
  206 + public void testCreateWxMpJsapiSignature() throws WxErrorException {
  207 + // 准备参数
  208 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  209 + String url = randomString();
  210 + // mock 方法
  211 + WxJsapiSignature signature = randomPojo(WxJsapiSignature.class);
  212 + when(wxMpService.createJsapiSignature(eq(url))).thenReturn(signature);
  213 +
  214 + // 调用
  215 + WxJsapiSignature result = socialClientService.createWxMpJsapiSignature(userType, url);
  216 + // 断言
  217 + assertSame(signature, result);
  218 + }
  219 +
  220 + @Test
  221 + public void testGetWxMpService_clientNull() {
  222 + // 准备参数
  223 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  224 + // mock 方法
  225 +
  226 + // 调用
  227 + WxMpService result = socialClientService.getWxMpService(userType);
  228 + // 断言
  229 + assertSame(wxMpService, result);
  230 + }
  231 +
  232 + @Test
  233 + public void testGetWxMpService_clientDisable() {
  234 + // 准备参数
  235 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  236 + // mock 数据
  237 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
  238 + .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
  239 + socialClientMapper.insert(client);
  240 +
  241 + // 调用
  242 + WxMpService result = socialClientService.getWxMpService(userType);
  243 + // 断言
  244 + assertSame(wxMpService, result);
  245 + }
  246 +
  247 + @Test
  248 + public void testGetWxMpService_clientEnable() {
  249 + // 准备参数
  250 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  251 + // mock 数据
  252 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  253 + .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
  254 + socialClientMapper.insert(client);
  255 + // mock 方法
  256 + WxMpProperties.ConfigStorage configStorage = mock(WxMpProperties.ConfigStorage.class);
  257 + when(wxMpProperties.getConfigStorage()).thenReturn(configStorage);
  258 +
  259 + // 调用
  260 + WxMpService result = socialClientService.getWxMpService(userType);
  261 + // 断言
  262 + assertNotSame(wxMpService, result);
  263 + assertEquals(client.getClientId(), result.getWxMpConfigStorage().getAppId());
  264 + assertEquals(client.getClientSecret(), result.getWxMpConfigStorage().getSecret());
  265 + }
  266 +
  267 + // =================== 微信小程序独有 ===================
  268 +
  269 + @Test
  270 + public void testGetWxMaPhoneNumberInfo_success() throws WxErrorException {
  271 + // 准备参数
  272 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  273 + String phoneCode = randomString();
  274 + // mock 方法
  275 + WxMaUserService userService = mock(WxMaUserService.class);
  276 + when(wxMaService.getUserService()).thenReturn(userService);
  277 + WxMaPhoneNumberInfo phoneNumber = randomPojo(WxMaPhoneNumberInfo.class);
  278 + when(userService.getPhoneNoInfo(eq(phoneCode))).thenReturn(phoneNumber);
  279 +
  280 + // 调用
  281 + WxMaPhoneNumberInfo result = socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode);
  282 + // 断言
  283 + assertSame(phoneNumber, result);
  284 + }
  285 +
  286 + @Test
  287 + public void testGetWxMaPhoneNumberInfo_exception() throws WxErrorException {
  288 + // 准备参数
  289 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  290 + String phoneCode = randomString();
  291 + // mock 方法
  292 + WxMaUserService userService = mock(WxMaUserService.class);
  293 + when(wxMaService.getUserService()).thenReturn(userService);
  294 + WxErrorException wxErrorException = randomPojo(WxErrorException.class);
  295 + when(userService.getPhoneNoInfo(eq(phoneCode))).thenThrow(wxErrorException);
  296 +
  297 + // 调用并断言异常
  298 + assertServiceException(() -> socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode),
  299 + SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR);
  300 + }
  301 +
  302 + @Test
  303 + public void testGetWxMaService_clientNull() {
  304 + // 准备参数
  305 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  306 + // mock 方法
  307 +
  308 + // 调用
  309 + WxMaService result = socialClientService.getWxMaService(userType);
  310 + // 断言
  311 + assertSame(wxMaService, result);
  312 + }
  313 +
  314 + @Test
  315 + public void testGetWxMaService_clientDisable() {
  316 + // 准备参数
  317 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  318 + // mock 数据
  319 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
  320 + .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
  321 + socialClientMapper.insert(client);
  322 +
  323 + // 调用
  324 + WxMaService result = socialClientService.getWxMaService(userType);
  325 + // 断言
  326 + assertSame(wxMaService, result);
  327 + }
  328 +
  329 + @Test
  330 + public void testGetWxMaService_clientEnable() {
  331 + // 准备参数
  332 + Integer userType = randomPojo(UserTypeEnum.class).getValue();
  333 + // mock 数据
  334 + SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  335 + .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
  336 + socialClientMapper.insert(client);
  337 + // mock 方法
  338 + WxMaProperties.ConfigStorage configStorage = mock(WxMaProperties.ConfigStorage.class);
  339 + when(wxMaProperties.getConfigStorage()).thenReturn(configStorage);
  340 +
  341 + // 调用
  342 + WxMaService result = socialClientService.getWxMaService(userType);
  343 + // 断言
  344 + assertNotSame(wxMaService, result);
  345 + assertEquals(client.getClientId(), result.getWxMaConfig().getAppid());
  346 + assertEquals(client.getClientSecret(), result.getWxMaConfig().getSecret());
  347 + }
  348 +
  349 + // =================== 客户端管理 ===================
  350 +
39 @Test 351 @Test
40 public void testCreateSocialClient_success() { 352 public void testCreateSocialClient_success() {
41 // 准备参数 353 // 准备参数
42 - SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class) 354 + SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class,
  355 + o -> o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
  356 + .setUserType(randomEle(UserTypeEnum.values()).getValue())
  357 + .setStatus(randomCommonStatus()))
43 .setId(null); // 防止 id 被赋值 358 .setId(null); // 防止 id 被赋值
44 359
45 // 调用 360 // 调用
@@ -59,6 +374,9 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest { @@ -59,6 +374,9 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest {
59 // 准备参数 374 // 准备参数
60 SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class, o -> { 375 SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class, o -> {
61 o.setId(dbSocialClient.getId()); // 设置更新的 ID 376 o.setId(dbSocialClient.getId()); // 设置更新的 ID
  377 + o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
  378 + .setUserType(randomEle(UserTypeEnum.values()).getValue())
  379 + .setStatus(randomCommonStatus());
62 }); 380 });
63 381
64 // 调用 382 // 调用
@@ -101,40 +419,47 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest { @@ -101,40 +419,47 @@ public class SocialClientServiceImplTest extends BaseDbUnitTest {
101 } 419 }
102 420
103 @Test 421 @Test
104 - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 422 + public void testGetSocialClient() {
  423 + // mock 数据
  424 + SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
  425 + socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
  426 + // 准备参数
  427 + Long id = dbSocialClient.getId();
  428 +
  429 + // 调用
  430 + SocialClientDO socialClient = socialClientService.getSocialClient(id);
  431 + // 校验数据正确
  432 + assertPojoEquals(dbSocialClient, socialClient);
  433 + }
  434 +
  435 + @Test
105 public void testGetSocialClientPage() { 436 public void testGetSocialClientPage() {
106 // mock 数据 437 // mock 数据
107 SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class, o -> { // 等会查询到 438 SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class, o -> { // 等会查询到
108 - o.setName(null);  
109 - o.setSocialType(null);  
110 - o.setUserType(null);  
111 - o.setClientId(null);  
112 - o.setClientSecret(null);  
113 - o.setStatus(null);  
114 - o.setCreateTime(null); 439 + o.setName("芋头");
  440 + o.setSocialType(SocialTypeEnum.GITEE.getType());
  441 + o.setUserType(UserTypeEnum.ADMIN.getValue());
  442 + o.setClientId("yudao");
  443 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
115 }); 444 });
116 socialClientMapper.insert(dbSocialClient); 445 socialClientMapper.insert(dbSocialClient);
117 // 测试 name 不匹配 446 // 测试 name 不匹配
118 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setName(null))); 447 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setName(randomString())));
119 // 测试 socialType 不匹配 448 // 测试 socialType 不匹配
120 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setSocialType(null))); 449 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setSocialType(SocialTypeEnum.DINGTALK.getType())));
121 // 测试 userType 不匹配 450 // 测试 userType 不匹配
122 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setUserType(null))); 451 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
123 // 测试 clientId 不匹配 452 // 测试 clientId 不匹配
124 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientId(null)));  
125 - // 测试 clientSecret 不匹配  
126 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientSecret(null))); 453 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientId("dao")));
127 // 测试 status 不匹配 454 // 测试 status 不匹配
128 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setStatus(null)));  
129 - // 测试 createTime 不匹配  
130 - socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setCreateTime(null))); 455 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
131 // 准备参数 456 // 准备参数
132 SocialClientPageReqVO reqVO = new SocialClientPageReqVO(); 457 SocialClientPageReqVO reqVO = new SocialClientPageReqVO();
133 - reqVO.setName(null);  
134 - reqVO.setSocialType(null);  
135 - reqVO.setUserType(null);  
136 - reqVO.setClientId(null);  
137 - reqVO.setStatus(null); 458 + reqVO.setName("芋");
  459 + reqVO.setSocialType(SocialTypeEnum.GITEE.getType());
  460 + reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
  461 + reqVO.setClientId("yu");
  462 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
138 463
139 // 调用 464 // 调用
140 PageResult<SocialClientDO> pageResult = socialClientService.getSocialClientPage(reqVO); 465 PageResult<SocialClientDO> pageResult = socialClientService.getSocialClientPage(reqVO);
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 5 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; 7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
  8 +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
7 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; 9 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
8 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 10 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
9 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; 11 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
10 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; 12 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
11 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 13 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
12 -import com.xingyuv.jushauth.enums.AuthResponseStatus;  
13 -import com.xingyuv.jushauth.model.AuthCallback;  
14 -import com.xingyuv.jushauth.model.AuthResponse;  
15 import com.xingyuv.jushauth.model.AuthUser; 14 import com.xingyuv.jushauth.model.AuthUser;
16 -import com.xingyuv.jushauth.request.AuthRequest;  
17 -import com.xingyuv.justauth.AuthRequestFactory;  
18 -import org.junit.jupiter.api.Disabled;  
19 import org.junit.jupiter.api.Test; 15 import org.junit.jupiter.api.Test;
20 import org.springframework.boot.test.mock.mockito.MockBean; 16 import org.springframework.boot.test.mock.mockito.MockBean;
21 import org.springframework.context.annotation.Import; 17 import org.springframework.context.annotation.Import;
@@ -23,18 +19,27 @@ import org.springframework.context.annotation.Import; @@ -23,18 +19,27 @@ import org.springframework.context.annotation.Import;
23 import javax.annotation.Resource; 19 import javax.annotation.Resource;
24 import java.util.List; 20 import java.util.List;
25 21
26 -import static cn.hutool.core.util.RandomUtil.*; 22 +import static cn.hutool.core.util.RandomUtil.randomEle;
  23 +import static cn.hutool.core.util.RandomUtil.randomLong;
  24 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
  25 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
27 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 26 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
  27 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
28 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 28 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
29 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 29 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
30 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 30 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
31 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_AUTH_FAILURE; 31 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
32 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND; 32 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
33 import static org.junit.jupiter.api.Assertions.assertEquals; 33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 -import static org.mockito.Mockito.*; 34 +import static org.mockito.Mockito.eq;
  35 +import static org.mockito.Mockito.when;
35 36
  37 +/**
  38 + * {@link SocialUserServiceImpl} 的单元测试类
  39 + *
  40 + * @author 芋道源码
  41 + */
36 @Import(SocialUserServiceImpl.class) 42 @Import(SocialUserServiceImpl.class)
37 -@Disabled // TODO 芋艿:后续统一修复  
38 public class SocialUserServiceImplTest extends BaseDbUnitTest { 43 public class SocialUserServiceImplTest extends BaseDbUnitTest {
39 44
40 @Resource 45 @Resource
@@ -46,119 +51,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { @@ -46,119 +51,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest {
46 private SocialUserBindMapper socialUserBindMapper; 51 private SocialUserBindMapper socialUserBindMapper;
47 52
48 @MockBean 53 @MockBean
49 - private AuthRequestFactory authRequestFactory;  
50 -  
51 - // TODO 芋艿:后续统一修复  
52 -// @Test  
53 -// public void testGetAuthorizeUrl() {  
54 -// try (MockedStatic<AuthStateUtils> authStateUtilsMock = mockStatic(AuthStateUtils.class)) {  
55 -// // 准备参数  
56 -// Integer type = SocialTypeEnum.WECHAT_MP.getType();  
57 -// String redirectUri = "sss";  
58 -// // mock 获得对应的 AuthRequest 实现  
59 -// AuthRequest authRequest = mock(AuthRequest.class);  
60 -// when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);  
61 -// // mock 方法  
62 -// authStateUtilsMock.when(AuthStateUtils::createState).thenReturn("aoteman");  
63 -// when(authRequest.authorize(eq("aoteman"))).thenReturn("https://www.iocoder.cn?redirect_uri=yyy");  
64 -//  
65 -// // 调用  
66 -// String url = socialUserService.getAuthorizeUrl(type, redirectUri);  
67 -// // 断言  
68 -// assertEquals("https://www.iocoder.cn?redirect_uri=sss", url);  
69 -// }  
70 -// }  
71 -  
72 - @Test  
73 - public void testAuthSocialUser_exists() {  
74 - // 准备参数  
75 - Integer socialType = SocialTypeEnum.GITEE.getType();  
76 - Integer userType = randomEle(SocialTypeEnum.values()).getType();  
77 - String code = "tudou";  
78 - String state = "yuanma";  
79 - // mock 方法  
80 - SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(socialType).setCode(code).setState(state);  
81 - socialUserMapper.insert(socialUser);  
82 -  
83 - // 调用  
84 - SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);  
85 - // 断言  
86 - assertPojoEquals(socialUser, result);  
87 - }  
88 -  
89 - @Test  
90 - public void testAuthSocialUser_authFailure() {  
91 - // 准备参数  
92 - Integer socialType = SocialTypeEnum.GITEE.getType();  
93 - Integer userType = randomEle(SocialTypeEnum.values()).getType();  
94 - // mock 方法  
95 - AuthRequest authRequest = mock(AuthRequest.class);  
96 - when(authRequestFactory.get(anyString())).thenReturn(authRequest);  
97 - AuthResponse<?> authResponse = new AuthResponse<>(0, "模拟失败", null);  
98 - when(authRequest.login(any(AuthCallback.class))).thenReturn(authResponse);  
99 -  
100 - // 调用并断言  
101 - assertServiceException(  
102 - () -> socialUserService.authSocialUser(socialType, userType, randomString(10), randomString(10)),  
103 - SOCIAL_USER_AUTH_FAILURE, "模拟失败");  
104 - }  
105 -  
106 - @Test  
107 - public void testAuthSocialUser_insert() {  
108 - // 准备参数  
109 - Integer socialType = SocialTypeEnum.GITEE.getType();  
110 - Integer userType = randomEle(SocialTypeEnum.values()).getType();  
111 - String code = "tudou";  
112 - String state = "yuanma";  
113 - // mock 方法  
114 - AuthRequest authRequest = mock(AuthRequest.class);  
115 - when(authRequestFactory.get(eq(SocialTypeEnum.GITEE.getSource()))).thenReturn(authRequest);  
116 - AuthUser authUser = randomPojo(AuthUser.class);  
117 - AuthResponse<AuthUser> authResponse = new AuthResponse<>(AuthResponseStatus.SUCCESS.getCode(), null, authUser);  
118 - when(authRequest.login(any(AuthCallback.class))).thenReturn(authResponse);  
119 -  
120 - // 调用  
121 - SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);  
122 - // 断言  
123 - assertBindSocialUser(socialType, result, authResponse.getData());  
124 - assertEquals(code, result.getCode());  
125 - assertEquals(state, result.getState());  
126 - }  
127 -  
128 - @Test  
129 - public void testAuthSocialUser_update() {  
130 - // 准备参数  
131 - Integer socialType = SocialTypeEnum.GITEE.getType();  
132 - Integer userType = randomEle(SocialTypeEnum.values()).getType();  
133 - String code = "tudou";  
134 - String state = "yuanma";  
135 - // mock 数据  
136 - socialUserMapper.insert(randomPojo(SocialUserDO.class).setType(socialType).setOpenid("test_openid"));  
137 - // mock 方法  
138 - AuthRequest authRequest = mock(AuthRequest.class);  
139 - when(authRequestFactory.get(eq(SocialTypeEnum.GITEE.getSource()))).thenReturn(authRequest);  
140 - AuthUser authUser = randomPojo(AuthUser.class);  
141 - authUser.getToken().setOpenId("test_openid");  
142 - AuthResponse<AuthUser> authResponse = new AuthResponse<>(AuthResponseStatus.SUCCESS.getCode(), null, authUser);  
143 - when(authRequest.login(any(AuthCallback.class))).thenReturn(authResponse);  
144 -  
145 - // 调用  
146 - SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);  
147 - // 断言  
148 - assertBindSocialUser(socialType, result, authResponse.getData());  
149 - assertEquals(code, result.getCode());  
150 - assertEquals(state, result.getState());  
151 - }  
152 -  
153 - private void assertBindSocialUser(Integer type, SocialUserDO socialUser, AuthUser authUser) {  
154 - assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());  
155 - assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());  
156 - assertEquals(authUser.getNickname(), socialUser.getNickname());  
157 - assertEquals(authUser.getAvatar(), socialUser.getAvatar());  
158 - assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());  
159 - assertEquals(type, socialUser.getType());  
160 - assertEquals(authUser.getUuid(), socialUser.getOpenid());  
161 - } 54 + private SocialClientService socialClientService;
162 55
163 @Test 56 @Test
164 public void testGetSocialUserList() { 57 public void testGetSocialUserList() {
@@ -260,4 +153,136 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { @@ -260,4 +153,136 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest {
260 assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid()); 153 assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid());
261 } 154 }
262 155
  156 + @Test
  157 + public void testAuthSocialUser_exists() {
  158 + // 准备参数
  159 + Integer socialType = SocialTypeEnum.GITEE.getType();
  160 + Integer userType = randomEle(SocialTypeEnum.values()).getType();
  161 + String code = "tudou";
  162 + String state = "yuanma";
  163 + // mock 方法
  164 + SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(socialType).setCode(code).setState(state);
  165 + socialUserMapper.insert(socialUser);
  166 +
  167 + // 调用
  168 + SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
  169 + // 断言
  170 + assertPojoEquals(socialUser, result);
  171 + }
  172 +
  173 + @Test
  174 + public void testAuthSocialUser_notNull() {
  175 + // mock 数据
  176 + SocialUserDO socialUser = randomPojo(SocialUserDO.class,
  177 + o -> o.setType(SocialTypeEnum.GITEE.getType()).setCode("tudou").setState("yuanma"));
  178 + socialUserMapper.insert(socialUser);
  179 + // 准备参数
  180 + Integer socialType = SocialTypeEnum.GITEE.getType();
  181 + Integer userType = randomEle(SocialTypeEnum.values()).getType();
  182 + String code = "tudou";
  183 + String state = "yuanma";
  184 +
  185 + // 调用
  186 + SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
  187 + // 断言
  188 + assertPojoEquals(socialUser, result);
  189 + }
  190 +
  191 + @Test
  192 + public void testAuthSocialUser_insert() {
  193 + // 准备参数
  194 + Integer socialType = SocialTypeEnum.GITEE.getType();
  195 + Integer userType = randomEle(SocialTypeEnum.values()).getType();
  196 + String code = "tudou";
  197 + String state = "yuanma";
  198 + // mock 方法
  199 + AuthUser authUser = randomPojo(AuthUser.class);
  200 + when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
  201 +
  202 + // 调用
  203 + SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
  204 + // 断言
  205 + assertBindSocialUser(socialType, result, authUser);
  206 + assertEquals(code, result.getCode());
  207 + assertEquals(state, result.getState());
  208 + }
  209 +
  210 + @Test
  211 + public void testAuthSocialUser_update() {
  212 + // 准备参数
  213 + Integer socialType = SocialTypeEnum.GITEE.getType();
  214 + Integer userType = randomEle(SocialTypeEnum.values()).getType();
  215 + String code = "tudou";
  216 + String state = "yuanma";
  217 + // mock 数据
  218 + socialUserMapper.insert(randomPojo(SocialUserDO.class).setType(socialType).setOpenid("test_openid"));
  219 + // mock 方法
  220 + AuthUser authUser = randomPojo(AuthUser.class);
  221 + when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
  222 +
  223 + // 调用
  224 + SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
  225 + // 断言
  226 + assertBindSocialUser(socialType, result, authUser);
  227 + assertEquals(code, result.getCode());
  228 + assertEquals(state, result.getState());
  229 + }
  230 +
  231 + private void assertBindSocialUser(Integer type, SocialUserDO socialUser, AuthUser authUser) {
  232 + assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());
  233 + assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());
  234 + assertEquals(authUser.getNickname(), socialUser.getNickname());
  235 + assertEquals(authUser.getAvatar(), socialUser.getAvatar());
  236 + assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());
  237 + assertEquals(type, socialUser.getType());
  238 + assertEquals(authUser.getUuid(), socialUser.getOpenid());
  239 + }
  240 +
  241 + @Test
  242 + public void testGetSocialUser_id() {
  243 + // mock 数据
  244 + SocialUserDO socialUserDO = randomPojo(SocialUserDO.class);
  245 + socialUserMapper.insert(socialUserDO);
  246 + // 参数准备
  247 + Long id = socialUserDO.getId();
  248 +
  249 + // 调用
  250 + SocialUserDO dbSocialUserDO = socialUserService.getSocialUser(id);
  251 + // 断言
  252 + assertPojoEquals(socialUserDO, dbSocialUserDO);
  253 + }
  254 +
  255 + @Test
  256 + public void testGetSocialUserPage() {
  257 + // mock 数据
  258 + SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, o -> { // 等会查询到
  259 + o.setType(SocialTypeEnum.GITEE.getType());
  260 + o.setNickname("芋艿");
  261 + o.setOpenid("yudaoyuanma");
  262 + o.setCreateTime(buildTime(2020, 1, 15));
  263 + });
  264 + socialUserMapper.insert(dbSocialUser);
  265 + // 测试 type 不匹配
  266 + socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setType(SocialTypeEnum.DINGTALK.getType())));
  267 + // 测试 nickname 不匹配
  268 + socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setNickname(randomString())));
  269 + // 测试 openid 不匹配
  270 + socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setOpenid("java")));
  271 + // 测试 createTime 不匹配
  272 + socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setCreateTime(buildTime(2020, 1, 21))));
  273 + // 准备参数
  274 + SocialUserPageReqVO reqVO = new SocialUserPageReqVO();
  275 + reqVO.setType(SocialTypeEnum.GITEE.getType());
  276 + reqVO.setNickname("芋");
  277 + reqVO.setOpenid("yudao");
  278 + reqVO.setCreateTime(buildBetweenTime(2020, 1, 10, 2020, 1, 20));
  279 +
  280 + // 调用
  281 + PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(reqVO);
  282 + // 断言
  283 + assertEquals(1, pageResult.getTotal());
  284 + assertEquals(1, pageResult.getList().size());
  285 + assertPojoEquals(dbSocialUser, pageResult.getList().get(0));
  286 + }
  287 +
263 } 288 }
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql
@@ -361,13 +361,14 @@ CREATE TABLE IF NOT EXISTS &quot;system_social_client&quot; ( @@ -361,13 +361,14 @@ CREATE TABLE IF NOT EXISTS &quot;system_social_client&quot; (
361 "user_type" int NOT NULL, 361 "user_type" int NOT NULL,
362 "client_id" varchar(255) NOT NULL, 362 "client_id" varchar(255) NOT NULL,
363 "client_secret" varchar(255) NOT NULL, 363 "client_secret" varchar(255) NOT NULL,
  364 + "agent_id" varchar(255) NOT NULL,
364 "status" int NOT NULL, 365 "status" int NOT NULL,
365 "creator" varchar(64) DEFAULT '', 366 "creator" varchar(64) DEFAULT '',
366 "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 367 "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
367 "updater" varchar(64) DEFAULT '', 368 "updater" varchar(64) DEFAULT '',
368 "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 369 "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
369 "deleted" bit NOT NULL DEFAULT FALSE, 370 "deleted" bit NOT NULL DEFAULT FALSE,
370 - "tenant_id" bigint NOT NULL, 371 + "tenant_id" bigint not null default '0',
371 PRIMARY KEY ("id") 372 PRIMARY KEY ("id")
372 ) COMMENT '社交客户端表'; 373 ) COMMENT '社交客户端表';
373 374