|
|
@@ -0,0 +1,393 @@
|
|
|
+package com.ruoyi.app.user;
|
|
|
+
|
|
|
+import com.ruoyi.app.user.dto.OAuthBindDto;
|
|
|
+import com.ruoyi.app.user.dto.OAuthDeviceConfirmDto;
|
|
|
+import com.ruoyi.app.user.dto.OAuthLoginDto;
|
|
|
+import com.ruoyi.system.domain.vo.UserDTO;
|
|
|
+import com.ruoyi.app.user.service.DeviceTrustService;
|
|
|
+import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
+import com.ruoyi.common.core.redis.RedisCache;
|
|
|
+import com.ruoyi.common.utils.spring.SpringUtils;
|
|
|
+import com.ruoyi.system.domain.InfoUser;
|
|
|
+import com.ruoyi.system.domain.InfoUserDevice;
|
|
|
+import com.ruoyi.system.domain.InfoUserOauth;
|
|
|
+import com.ruoyi.system.mapper.InfoUserDeviceMapper;
|
|
|
+import com.ruoyi.system.mapper.InfoUserOauthMapper;
|
|
|
+import com.ruoyi.system.service.IInfoUserService;
|
|
|
+import org.junit.jupiter.api.AfterAll;
|
|
|
+import org.junit.jupiter.api.AfterEach;
|
|
|
+import org.junit.jupiter.api.BeforeAll;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
|
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|
|
+import org.springframework.context.support.StaticMessageSource;
|
|
|
+import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
+import org.springframework.test.util.ReflectionTestUtils;
|
|
|
+import org.springframework.web.context.request.RequestContextHolder;
|
|
|
+import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
+
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import static org.mockito.ArgumentMatchers.any;
|
|
|
+import static org.mockito.ArgumentMatchers.anyString;
|
|
|
+import static org.mockito.ArgumentMatchers.argThat;
|
|
|
+import static org.mockito.ArgumentMatchers.eq;
|
|
|
+import static org.mockito.ArgumentMatchers.startsWith;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.never;
|
|
|
+import static org.mockito.Mockito.verify;
|
|
|
+import static org.mockito.Mockito.verifyNoInteractions;
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 设备信任免绑端到端分支测试(029-device-trust-phone-bind,TDD 先行)。
|
|
|
+ * 直接以 Mockito 实例化 InfoUserController,走 oauthLogin/oauthDeviceConfirm/oauthBindPhone/lodeing
|
|
|
+ * 的关键分支;JwtUtil/MessageUtils 通过 SpringUtils 静态 BeanFactory 替换为测试桩。
|
|
|
+ */
|
|
|
+class DeviceTrustFlowTest {
|
|
|
+
|
|
|
+ private static ConfigurableListableBeanFactory originalBeanFactory;
|
|
|
+
|
|
|
+ private final RedisCache redisCache = mock(RedisCache.class);
|
|
|
+ private final IInfoUserService infoUserService = mock(IInfoUserService.class);
|
|
|
+ private final InfoUserOauthMapper infoUserOauthMapper = mock(InfoUserOauthMapper.class);
|
|
|
+ private final com.ruoyi.app.utils.oauth.OAuthVerifyService oauthVerifyService =
|
|
|
+ mock(com.ruoyi.app.utils.oauth.OAuthVerifyService.class);
|
|
|
+ private final com.ruoyi.system.service.IUserWalletService userWalletService =
|
|
|
+ mock(com.ruoyi.system.service.IUserWalletService.class);
|
|
|
+ private final com.ruoyi.system.service.IVipUserService vipUserService =
|
|
|
+ mock(com.ruoyi.system.service.IVipUserService.class);
|
|
|
+ private final InfoUserDeviceMapper deviceMapper = mock(InfoUserDeviceMapper.class);
|
|
|
+
|
|
|
+ private InfoUserController controller;
|
|
|
+
|
|
|
+ @BeforeAll
|
|
|
+ static void initStatics() {
|
|
|
+ originalBeanFactory = (ConfigurableListableBeanFactory)
|
|
|
+ ReflectionTestUtils.getField(SpringUtils.class, "beanFactory");
|
|
|
+ }
|
|
|
+
|
|
|
+ @AfterAll
|
|
|
+ static void restoreStatics() {
|
|
|
+ new SpringUtils().postProcessBeanFactory(originalBeanFactory);
|
|
|
+ JwtUtilRestore.restore();
|
|
|
+ }
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ void setUp() {
|
|
|
+ // MessageUtils:返回 key 本身;JwtUtil 的 getBean(RedisCache) 也从这个工厂取
|
|
|
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
|
|
+ StaticMessageSource messageSource = new StaticMessageSource();
|
|
|
+ messageSource.setUseCodeAsDefaultMessage(true);
|
|
|
+ beanFactory.registerSingleton("messageSource", messageSource);
|
|
|
+ beanFactory.registerSingleton("redisCache", redisCache);
|
|
|
+ new SpringUtils().postProcessBeanFactory(beanFactory);
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
|
|
|
+
|
|
|
+ controller = new InfoUserController();
|
|
|
+ ReflectionTestUtils.setField(controller, "redisCache", redisCache);
|
|
|
+ ReflectionTestUtils.setField(controller, "infoUserService", infoUserService);
|
|
|
+ ReflectionTestUtils.setField(controller, "infoUserOauthMapper", infoUserOauthMapper);
|
|
|
+ ReflectionTestUtils.setField(controller, "oauthVerifyService", oauthVerifyService);
|
|
|
+ ReflectionTestUtils.setField(controller, "userWalletService", userWalletService);
|
|
|
+ ReflectionTestUtils.setField(controller, "vipUserService", vipUserService);
|
|
|
+ ReflectionTestUtils.setField(controller, "deviceTrustService", new DeviceTrustService(deviceMapper));
|
|
|
+ }
|
|
|
+
|
|
|
+ @AfterEach
|
|
|
+ void tearDown() {
|
|
|
+ RequestContextHolder.resetRequestAttributes();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** JwtUtil 静态依赖还原占位(当前版本经 SpringUtils 取 Bean,无需额外清理) */
|
|
|
+ private static final class JwtUtilRestore {
|
|
|
+ static void restore() {
|
|
|
+ // JwtUtil.setToken 每次经 SpringUtils.getBean 动态获取,无静态持有,无需还原
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static InfoUser user(long id, String phone, String status) {
|
|
|
+ InfoUser u = new InfoUser();
|
|
|
+ u.setUserId(id);
|
|
|
+ u.setPhone(phone);
|
|
|
+ u.setStatus(status);
|
|
|
+ u.setDelFlag("0");
|
|
|
+ return u;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static InfoUserDevice trust(String deviceId, String phone, long userId) {
|
|
|
+ InfoUserDevice t = new InfoUserDevice();
|
|
|
+ t.setDeviceId(deviceId);
|
|
|
+ t.setPhone(phone);
|
|
|
+ t.setUserId(userId);
|
|
|
+ return t;
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private static Map<String, Object> dataMap(AjaxResult result) {
|
|
|
+ return (Map<String, Object>) result.get("data");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== oauthLogin 分支 ====================
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void oauthLoginUnboundWithTrustedDeviceReturnsDeviceConfirmAndWritesBothKeys() {
|
|
|
+ when(oauthVerifyService.verify("google", "cred-1")).thenReturn("uid-1");
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0987654321", 100L));
|
|
|
+
|
|
|
+ OAuthLoginDto dto = new OAuthLoginDto();
|
|
|
+ dto.setProvider("google");
|
|
|
+ dto.setCredential("cred-1");
|
|
|
+ dto.setDeviceId("dev-1");
|
|
|
+ AjaxResult result = controller.oauthLogin(dto);
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ Map<String, Object> data = dataMap(result);
|
|
|
+ assertEquals("deviceConfirm", data.get("status"));
|
|
|
+ assertNotNull(data.get("tempKey"));
|
|
|
+ assertEquals("098****4321", data.get("maskedPhone"));
|
|
|
+ String tempKey = (String) data.get("tempKey");
|
|
|
+ verify(redisCache).setCacheObject(eq("oauth:bind:" + tempKey), eq("google@uid-1"), eq(5), eq(TimeUnit.MINUTES));
|
|
|
+ verify(redisCache).setCacheObject(eq("oauth:bind:dev:" + tempKey), eq("dev-1"), eq(5), eq(TimeUnit.MINUTES));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void oauthLoginUnboundWithoutDeviceIdStillReturnsNeedPhone() {
|
|
|
+ when(oauthVerifyService.verify("google", "cred-1")).thenReturn("uid-1");
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+
|
|
|
+ OAuthLoginDto dto = new OAuthLoginDto();
|
|
|
+ dto.setProvider("google");
|
|
|
+ dto.setCredential("cred-1");
|
|
|
+ AjaxResult result = controller.oauthLogin(dto);
|
|
|
+
|
|
|
+ Map<String, Object> data = dataMap(result);
|
|
|
+ assertEquals("needPhone", data.get("status"));
|
|
|
+ assertNotNull(data.get("tempKey"));
|
|
|
+ assertNull(data.get("maskedPhone"));
|
|
|
+ verify(redisCache, never()).setCacheObject(startsWith("oauth:bind:dev:"), anyString(), eq(5), eq(TimeUnit.MINUTES));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void oauthLoginUnboundWithUnknownDeviceStillReturnsNeedPhone() {
|
|
|
+ when(oauthVerifyService.verify("apple", "cred-2")).thenReturn("uid-2");
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+ when(deviceMapper.selectById("dev-x")).thenReturn(null);
|
|
|
+
|
|
|
+ OAuthLoginDto dto = new OAuthLoginDto();
|
|
|
+ dto.setProvider("apple");
|
|
|
+ dto.setCredential("cred-2");
|
|
|
+ dto.setDeviceId("dev-x");
|
|
|
+ AjaxResult result = controller.oauthLogin(dto);
|
|
|
+
|
|
|
+ assertEquals("needPhone", dataMap(result).get("status"));
|
|
|
+ verify(redisCache, never()).setCacheObject(startsWith("oauth:bind:dev:"), anyString(), eq(5), eq(TimeUnit.MINUTES));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== oauthDeviceConfirm ====================
|
|
|
+
|
|
|
+ private void stubConfirmRedis(String tempKey, String deviceId) {
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:" + tempKey)).thenReturn("google@uid-1");
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:dev:" + tempKey)).thenReturn(deviceId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private OAuthDeviceConfirmDto confirmDto(String tempKey, String deviceId) {
|
|
|
+ OAuthDeviceConfirmDto dto = new OAuthDeviceConfirmDto();
|
|
|
+ dto.setTempKey(tempKey);
|
|
|
+ dto.setDeviceId(deviceId);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmBindsTrustedPhoneExistingUserAndIssuesToken() {
|
|
|
+ stubConfirmRedis("tk-1", "dev-1");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0987654321", 100L));
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+ InfoUser existing = user(100L, "0987654321", "0");
|
|
|
+ when(infoUserService.getuser("0987654321")).thenReturn(existing);
|
|
|
+
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-1", "dev-1"));
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertEquals("no.user.login.success", result.get("msg"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(infoUserOauthMapper).insert(org.mockito.ArgumentMatchers.<InfoUserOauth>argThat(b -> "google".equals(b.getProvider())
|
|
|
+ && "uid-1".equals(b.getProviderUid()) && b.getUserId() == 100L));
|
|
|
+ verify(redisCache).deleteObject("oauth:bind:tk-1");
|
|
|
+ verify(redisCache).deleteObject("oauth:bind:dev:tk-1");
|
|
|
+ // recordLogin:同设备同号刷新信任
|
|
|
+ verify(deviceMapper).updateById(any(InfoUserDevice.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmCreatesUserWhenTrustedPhoneNotRegistered() {
|
|
|
+ stubConfirmRedis("tk-2", "dev-1");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0999888777", 0L));
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+ when(infoUserService.getuser("0999888777")).thenReturn(null, user(300L, "0999888777", "0"));
|
|
|
+
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-2", "dev-1"));
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(userWalletService).createUserWallet(300L);
|
|
|
+ verify(infoUserOauthMapper).insert(org.mockito.ArgumentMatchers.<InfoUserOauth>argThat(b -> b.getUserId() == 300L));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmExpiredTempKeyReturnsExpiredError() {
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:tk-3")).thenReturn(null);
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-3", "dev-1"));
|
|
|
+ assertEquals(500, result.get("code"));
|
|
|
+ assertEquals("no.oauth.tempkey.expired", result.get("msg"));
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmWithDeviceMismatchOrMissingDevKeyIsRejected() {
|
|
|
+ stubConfirmRedis("tk-4", "dev-other");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0987654321", 100L));
|
|
|
+
|
|
|
+ AjaxResult wrongDevice = controller.oauthDeviceConfirm(confirmDto("tk-4", "dev-1"));
|
|
|
+ assertEquals("no.oauth.device.mismatch", wrongDevice.get("msg"));
|
|
|
+
|
|
|
+ // dev 键缺失(tempKey 来自 needPhone 分支)
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:tk-5")).thenReturn("google@uid-1");
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:dev:tk-5")).thenReturn(null);
|
|
|
+ AjaxResult noDevKey = controller.oauthDeviceConfirm(confirmDto("tk-5", "dev-1"));
|
|
|
+ assertEquals("no.oauth.device.mismatch", noDevKey.get("msg"));
|
|
|
+
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmWhenTrustRowGoneIsRejected() {
|
|
|
+ stubConfirmRedis("tk-6", "dev-1");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(null);
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-6", "dev-1"));
|
|
|
+ assertEquals("no.oauth.device.mismatch", result.get("msg"));
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmRejectedWhenTrustedAccountStopped() {
|
|
|
+ stubConfirmRedis("tk-7", "dev-1");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0987654321", 100L));
|
|
|
+ when(infoUserService.getuser("0987654321")).thenReturn(user(100L, "0987654321", "1"));
|
|
|
+
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-7", "dev-1"));
|
|
|
+ assertEquals("no.user.stop", result.get("msg"));
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void confirmFallsBackToDirectLoginWhenBoundMeanwhile() {
|
|
|
+ stubConfirmRedis("tk-8", "dev-1");
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(trust("dev-1", "0987654321", 100L));
|
|
|
+ InfoUserOauth exist = new InfoUserOauth();
|
|
|
+ exist.setUserId(100L);
|
|
|
+ exist.setProvider("google");
|
|
|
+ exist.setProviderUid("uid-1");
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(exist);
|
|
|
+ when(infoUserService.getById(100L)).thenReturn(user(100L, "0987654321", "0"));
|
|
|
+
|
|
|
+ AjaxResult result = controller.oauthDeviceConfirm(confirmDto("tk-8", "dev-1"));
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 记录点(US2) ====================
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void phoneLoginSuccessRecordsDeviceTrust() {
|
|
|
+ when(redisCache.getCacheObject("0987654321")).thenReturn(null);
|
|
|
+ InfoUser existing = user(100L, "0987654321", "0");
|
|
|
+ when(infoUserService.getuser("0987654321")).thenReturn(existing);
|
|
|
+ when(infoUserService.getOne(any())).thenReturn(existing);
|
|
|
+ when(vipUserService.getOne(any())).thenReturn(null);
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(null);
|
|
|
+
|
|
|
+ UserDTO dto = new UserDTO();
|
|
|
+ dto.setPhone("0987654321");
|
|
|
+ dto.setCode("8888");
|
|
|
+ dto.setDeviceId("dev-1");
|
|
|
+ AjaxResult result = controller.lodeing(dto);
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(deviceMapper).insert(org.mockito.ArgumentMatchers.<InfoUserDevice>argThat(row -> "dev-1".equals(row.getDeviceId())
|
|
|
+ && "0987654321".equals(row.getPhone()) && row.getUserId() == 100L));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void phoneLoginWithoutDeviceIdSkipsRecording() {
|
|
|
+ when(redisCache.getCacheObject("0987654321")).thenReturn("1234");
|
|
|
+ InfoUser existing = user(100L, "0987654321", "0");
|
|
|
+ when(infoUserService.getuser("0987654321")).thenReturn(existing);
|
|
|
+ when(infoUserService.getOne(any())).thenReturn(existing);
|
|
|
+ when(vipUserService.getOne(any())).thenReturn(null);
|
|
|
+
|
|
|
+ UserDTO dto = new UserDTO();
|
|
|
+ dto.setPhone("0987654321");
|
|
|
+ dto.setCode("1234");
|
|
|
+ AjaxResult result = controller.lodeing(dto);
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ verifyNoInteractions(deviceMapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void oauthBindPhoneSuccessRecordsDeviceTrust() {
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:tk-b1")).thenReturn("google@uid-9");
|
|
|
+ when(redisCache.getCacheObject("0987654321")).thenReturn(null);
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(null);
|
|
|
+ InfoUser existing = user(100L, "0987654321", "0");
|
|
|
+ when(infoUserService.getuser("0987654321")).thenReturn(existing);
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(null);
|
|
|
+
|
|
|
+ OAuthBindDto dto = new OAuthBindDto();
|
|
|
+ dto.setTempKey("tk-b1");
|
|
|
+ dto.setPhone("0987654321");
|
|
|
+ dto.setCode("8888");
|
|
|
+ dto.setDeviceId("dev-1");
|
|
|
+ AjaxResult result = controller.oauthBindPhone(dto);
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(deviceMapper).insert(any(InfoUserDevice.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void oauthLoginBoundDirectLoginRecordsDeviceTrust() {
|
|
|
+ when(oauthVerifyService.verify("line", "cred-3")).thenReturn("uid-3");
|
|
|
+ InfoUserOauth bind = new InfoUserOauth();
|
|
|
+ bind.setUserId(100L);
|
|
|
+ bind.setProvider("line");
|
|
|
+ bind.setProviderUid("uid-3");
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(bind);
|
|
|
+ InfoUser existing = user(100L, "0987654321", "0");
|
|
|
+ when(infoUserService.getOne(any())).thenReturn(existing);
|
|
|
+ when(deviceMapper.selectById("dev-1")).thenReturn(null);
|
|
|
+
|
|
|
+ OAuthLoginDto dto = new OAuthLoginDto();
|
|
|
+ dto.setProvider("line");
|
|
|
+ dto.setCredential("cred-3");
|
|
|
+ dto.setDeviceId("dev-1");
|
|
|
+ AjaxResult result = controller.oauthLogin(dto);
|
|
|
+
|
|
|
+ assertEquals(200, result.get("code"));
|
|
|
+ assertNotNull(result.get("token"));
|
|
|
+ verify(deviceMapper).insert(org.mockito.ArgumentMatchers.<InfoUserDevice>argThat(row -> "0987654321".equals(row.getPhone())));
|
|
|
+ }
|
|
|
+}
|