feat(admin): 添加用户管理相关文件

添加用户管理视图、API和状态管理文件
This commit is contained in:
张翔
2026-03-28 14:37:29 +08:00
commit 08ea5fbe98
1643 changed files with 255646 additions and 0 deletions
@@ -0,0 +1,231 @@
package io.destiny.client.client;
import io.destiny.client.config.DouyinMiniProgramConfig;
import io.destiny.client.core.exception.ClientUserAuthExceptionCode;
import io.destiny.client.dto.WechatAuthResponse;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.function.Function;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@SuppressWarnings({"unchecked", "rawtypes"})
class DouyinMiniProgramClientTest {
@Mock
private WebClient webClient;
@Mock
private WebClient.RequestHeadersUriSpec requestHeadersUriSpec;
@Mock
private WebClient.RequestHeadersSpec requestHeadersSpec;
@Mock
private WebClient.ResponseSpec responseSpec;
@Mock
private DouyinMiniProgramConfig config;
private DouyinMiniProgramClient douyinMiniProgramClient;
private static final String TEST_CODE = "test_code_123";
private static final String TEST_APP_ID = "test_app_id";
private static final String TEST_APP_SECRET = "test_app_secret";
private static final String TEST_OPEN_ID = "test_open_id";
private static final String TEST_SESSION_KEY = "test_session_key";
private static final String TEST_UNION_ID = "test_union_id";
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
when(config.getAppId()).thenReturn(TEST_APP_ID);
when(config.getAppSecret()).thenReturn(TEST_APP_SECRET);
douyinMiniProgramClient = new DouyinMiniProgramClient(config, webClient);
}
@Test
void testAuth_Success() {
String successResponse = String.format("{\"err_no\":0,\"err_tips\":\"success\",\"data\":{\"openid\":\"%s\",\"session_key\":\"%s\",\"unionid\":\"%s\"}}",
TEST_OPEN_ID, TEST_SESSION_KEY, TEST_UNION_ID);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(successResponse));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectNextMatches(response ->
TEST_OPEN_ID.equals(response.getOpenId()) &&
TEST_SESSION_KEY.equals(response.getSessionKey()) &&
TEST_UNION_ID.equals(response.getUnionId()))
.verifyComplete();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_WebClientResponseException() {
WebClientResponseException exception = WebClientResponseException.create(
400, "Bad Request", null, "{\"errcode\":40029,\"errmsg\":\"invalid code\"}".getBytes(), null);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.error(exception));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_GeneralException() {
RuntimeException exception = new RuntimeException("Network error");
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.error(exception));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_InvalidResponseFormat() {
String invalidResponse = "invalid json";
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(invalidResponse));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_ResponseWithoutUnionId() {
String responseWithoutUnionId = String.format("{\"err_no\":0,\"err_tips\":\"success\",\"data\":{\"openid\":\"%s\",\"session_key\":\"%s\"}}",
TEST_OPEN_ID, TEST_SESSION_KEY);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(responseWithoutUnionId));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectNextMatches(response ->
TEST_OPEN_ID.equals(response.getOpenId()) &&
TEST_SESSION_KEY.equals(response.getSessionKey()) &&
response.getUnionId() == null)
.verifyComplete();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_ApiError() {
String errorResponse = "{\"err_no\":40029,\"err_tips\":\"invalid code\"}";
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(errorResponse));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_ResponseWithoutData() {
String responseWithoutData = "{\"err_no\":0,\"err_tips\":\"success\"}";
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(responseWithoutData));
Mono<WechatAuthResponse> result = douyinMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
}
@@ -0,0 +1,183 @@
package io.destiny.client.client;
import io.destiny.client.config.WechatMiniProgramConfig;
import io.destiny.client.core.exception.ClientUserAuthExceptionCode;
import io.destiny.client.dto.WechatAuthResponse;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.function.Function;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@SuppressWarnings({"unchecked", "rawtypes"})
class WechatMiniProgramClientTest {
@Mock
private WebClient webClient;
@Mock
private WebClient.RequestHeadersUriSpec requestHeadersUriSpec;
@Mock
private WebClient.RequestHeadersSpec requestHeadersSpec;
@Mock
private WebClient.ResponseSpec responseSpec;
@Mock
private WechatMiniProgramConfig config;
private WechatMiniProgramClient wechatMiniProgramClient;
private static final String TEST_CODE = "test_code_123";
private static final String TEST_APP_ID = "test_app_id";
private static final String TEST_APP_SECRET = "test_app_secret";
private static final String TEST_OPEN_ID = "test_open_id";
private static final String TEST_SESSION_KEY = "test_session_key";
private static final String TEST_UNION_ID = "test_union_id";
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
when(config.getAppId()).thenReturn(TEST_APP_ID);
when(config.getAppSecret()).thenReturn(TEST_APP_SECRET);
wechatMiniProgramClient = new WechatMiniProgramClient(config, webClient);
}
@Test
void testAuth_Success() {
String successResponse = String.format("{\"openid\":\"%s\",\"session_key\":\"%s\",\"unionid\":\"%s\"}",
TEST_OPEN_ID, TEST_SESSION_KEY, TEST_UNION_ID);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(successResponse));
Mono<WechatAuthResponse> result = wechatMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectNextMatches(response ->
TEST_OPEN_ID.equals(response.getOpenId()) &&
TEST_SESSION_KEY.equals(response.getSessionKey()) &&
TEST_UNION_ID.equals(response.getUnionId()))
.verifyComplete();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_WebClientResponseException() {
WebClientResponseException exception = WebClientResponseException.create(
400, "Bad Request", null, "{\"errcode\":40029,\"errmsg\":\"invalid code\"}".getBytes(), null);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.error(exception));
Mono<WechatAuthResponse> result = wechatMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_GeneralException() {
RuntimeException exception = new RuntimeException("Network error");
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.error(exception));
Mono<WechatAuthResponse> result = wechatMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_InvalidResponseFormat() {
String invalidResponse = "invalid json";
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(invalidResponse));
Mono<WechatAuthResponse> result = wechatMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED))
.verify();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
@Test
void testAuth_ResponseWithoutUnionId() {
String responseWithoutUnionId = String.format("{\"openid\":\"%s\",\"session_key\":\"%s\"}",
TEST_OPEN_ID, TEST_SESSION_KEY);
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString(), any(Function.class))).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.accept(MediaType.APPLICATION_JSON)).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(responseWithoutUnionId));
Mono<WechatAuthResponse> result = wechatMiniProgramClient.auth(TEST_CODE);
StepVerifier.create(result)
.expectNextMatches(response ->
TEST_OPEN_ID.equals(response.getOpenId()) &&
TEST_SESSION_KEY.equals(response.getSessionKey()) &&
response.getUnionId() == null)
.verifyComplete();
verify(webClient, times(1)).get();
verify(requestHeadersUriSpec, times(1)).uri(anyString(), any(Function.class));
verify(requestHeadersUriSpec, times(1)).accept(MediaType.APPLICATION_JSON);
verify(requestHeadersSpec, times(1)).retrieve();
verify(responseSpec, times(1)).bodyToMono(String.class);
}
}
@@ -0,0 +1,55 @@
package io.destiny.client.config;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AliyunSmsConfigTest {
private AliyunSmsConfig aliyunSmsConfig;
@BeforeEach
void setUp() {
aliyunSmsConfig = new AliyunSmsConfig();
}
@Test
void testGettersAndSetters_Success() {
aliyunSmsConfig.setAccessKeyId("testAccessKeyId");
aliyunSmsConfig.setAccessKeySecret("testAccessKeySecret");
aliyunSmsConfig.setEndpoint("testEndpoint");
aliyunSmsConfig.setSignName("testSignName");
aliyunSmsConfig.setTemplateCode("testTemplateCode");
assertEquals("testAccessKeyId", aliyunSmsConfig.getAccessKeyId());
assertEquals("testAccessKeySecret", aliyunSmsConfig.getAccessKeySecret());
assertEquals("testEndpoint", aliyunSmsConfig.getEndpoint());
assertEquals("testSignName", aliyunSmsConfig.getSignName());
assertEquals("testTemplateCode", aliyunSmsConfig.getTemplateCode());
}
@Test
void testDefaultValues_Success() {
assertEquals(10, aliyunSmsConfig.getExpireMinutes());
assertEquals(60, aliyunSmsConfig.getSendIntervalSeconds());
assertEquals(10, aliyunSmsConfig.getMaxSendCountPerDay());
assertEquals(5, aliyunSmsConfig.getMaxVerifyAttempts());
assertEquals(10, aliyunSmsConfig.getLockMinutes());
}
@Test
void testCustomValues_Success() {
aliyunSmsConfig.setExpireMinutes(5);
aliyunSmsConfig.setSendIntervalSeconds(30);
aliyunSmsConfig.setMaxSendCountPerDay(20);
aliyunSmsConfig.setMaxVerifyAttempts(3);
aliyunSmsConfig.setLockMinutes(15);
assertEquals(5, aliyunSmsConfig.getExpireMinutes());
assertEquals(30, aliyunSmsConfig.getSendIntervalSeconds());
assertEquals(20, aliyunSmsConfig.getMaxSendCountPerDay());
assertEquals(3, aliyunSmsConfig.getMaxVerifyAttempts());
assertEquals(15, aliyunSmsConfig.getLockMinutes());
}
}
@@ -0,0 +1,31 @@
package io.destiny.client.config;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class DouyinMiniProgramConfigTest {
private DouyinMiniProgramConfig douyinMiniProgramConfig;
@BeforeEach
void setUp() {
douyinMiniProgramConfig = new DouyinMiniProgramConfig();
}
@Test
void testGettersAndSetters_Success() {
douyinMiniProgramConfig.setAppId("testAppId");
douyinMiniProgramConfig.setAppSecret("testAppSecret");
assertEquals("testAppId", douyinMiniProgramConfig.getAppId());
assertEquals("testAppSecret", douyinMiniProgramConfig.getAppSecret());
}
@Test
void testNullValues_Success() {
assertNull(douyinMiniProgramConfig.getAppId());
assertNull(douyinMiniProgramConfig.getAppSecret());
}
}
@@ -0,0 +1,31 @@
package io.destiny.client.config;
import com.aliyun.dysmsapi20170525.Client;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
class SmsClientConfigTest {
private SmsClientConfig smsClientConfig;
@Mock
private AliyunSmsConfig smsConfig;
@BeforeEach
void setUp() {
smsClientConfig = new SmsClientConfig();
}
@Test
void testSmsClientBean_Success() throws Exception {
Client client = smsClientConfig.smsClient(smsConfig);
assertNotNull(client);
}
}
@@ -0,0 +1,31 @@
package io.destiny.client.config;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class WechatMiniProgramConfigTest {
private WechatMiniProgramConfig wechatMiniProgramConfig;
@BeforeEach
void setUp() {
wechatMiniProgramConfig = new WechatMiniProgramConfig();
}
@Test
void testGettersAndSetters_Success() {
wechatMiniProgramConfig.setAppId("testAppId");
wechatMiniProgramConfig.setAppSecret("testAppSecret");
assertEquals("testAppId", wechatMiniProgramConfig.getAppId());
assertEquals("testAppSecret", wechatMiniProgramConfig.getAppSecret());
}
@Test
void testNullValues_Success() {
assertNull(wechatMiniProgramConfig.getAppId());
assertNull(wechatMiniProgramConfig.getAppSecret());
}
}
@@ -0,0 +1,171 @@
package io.destiny.client.core.domain;
import io.destiny.common.primitive.IpAddress;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class ClientLoginLogTest {
private static final Long TEST_ID = 12345L;
private static final Long TEST_CLIENT_USER_ID = 67890L;
private static final IpAddress TEST_IP_ADDRESS = IpAddress.of("192.168.1.1");
@Test
void testConstructor_DefaultValues() {
ClientLoginLog log = new ClientLoginLog();
assertNull(log.getId());
assertNull(log.getClientUserId());
assertNull(log.getIpAddress());
assertNull(log.getLoginTime());
assertNull(log.getLogoutTime());
assertNull(log.getCreatedAt());
assertNull(log.getUpdatedAt());
assertNull(log.getDeletedAt());
}
@Test
void testConstructor_WithParameters() {
ClientLoginLog log = new ClientLoginLog(TEST_CLIENT_USER_ID, TEST_IP_ADDRESS);
assertNotNull(log.getId());
assertTrue(log.getId() > 0);
assertEquals(TEST_CLIENT_USER_ID, log.getClientUserId());
assertEquals(TEST_IP_ADDRESS, log.getIpAddress());
assertNotNull(log.getLoginTime());
assertTrue(log.getLoginTime().isBefore(LocalDateTime.now().plusSeconds(1)));
assertTrue(log.getLoginTime().isAfter(LocalDateTime.now().minusSeconds(1)));
assertNull(log.getLogoutTime());
assertNull(log.getCreatedAt());
assertNull(log.getUpdatedAt());
assertNull(log.getDeletedAt());
}
@Test
void testGettersAndSetters() {
ClientLoginLog log = new ClientLoginLog();
log.setId(TEST_ID);
log.setClientUserId(TEST_CLIENT_USER_ID);
log.setIpAddress(TEST_IP_ADDRESS);
LocalDateTime testLoginTime = LocalDateTime.now().minusHours(1);
LocalDateTime testLogoutTime = LocalDateTime.now().minusMinutes(30);
LocalDateTime testCreatedAt = LocalDateTime.now().minusDays(1);
LocalDateTime testUpdatedAt = LocalDateTime.now().minusHours(1);
LocalDateTime testDeletedAt = LocalDateTime.now();
log.setLoginTime(testLoginTime);
log.setLogoutTime(testLogoutTime);
log.setCreatedAt(testCreatedAt);
log.setUpdatedAt(testUpdatedAt);
log.setDeletedAt(testDeletedAt);
assertEquals(TEST_ID, log.getId());
assertEquals(TEST_CLIENT_USER_ID, log.getClientUserId());
assertEquals(TEST_IP_ADDRESS, log.getIpAddress());
assertEquals(testLoginTime, log.getLoginTime());
assertEquals(testLogoutTime, log.getLogoutTime());
assertEquals(testCreatedAt, log.getCreatedAt());
assertEquals(testUpdatedAt, log.getUpdatedAt());
assertEquals(testDeletedAt, log.getDeletedAt());
}
@Test
void testGenerateId_SetsUniqueId() {
ClientLoginLog log = new ClientLoginLog();
log.generateId();
assertNotNull(log.getId());
assertTrue(log.getId() > 0);
}
@Test
void testGenerateId_GeneratesDifferentIds() {
ClientLoginLog log1 = new ClientLoginLog();
ClientLoginLog log2 = new ClientLoginLog();
log1.generateId();
log2.generateId();
assertNotNull(log1.getId());
assertNotNull(log2.getId());
assertNotEquals(log1.getId(), log2.getId());
}
@Test
void testGenerateId_OverwritesExistingId() {
ClientLoginLog log = new ClientLoginLog();
log.setId(TEST_ID);
log.generateId();
assertNotEquals(TEST_ID, log.getId());
assertNotNull(log.getId());
}
@Test
void testDelete_SetsDeletedAt() {
ClientLoginLog log = new ClientLoginLog();
assertNull(log.getDeletedAt());
log.delete();
assertNotNull(log.getDeletedAt());
assertTrue(log.getDeletedAt().isBefore(LocalDateTime.now().plusSeconds(1)));
assertTrue(log.getDeletedAt().isAfter(LocalDateTime.now().minusSeconds(1)));
}
@Test
void testDelete_CanBeCalledMultipleTimes() {
ClientLoginLog log = new ClientLoginLog();
log.delete();
LocalDateTime firstDeletedAt = log.getDeletedAt();
log.delete();
LocalDateTime secondDeletedAt = log.getDeletedAt();
assertNotNull(secondDeletedAt);
assertNotEquals(firstDeletedAt, secondDeletedAt);
}
@Test
void testIsLogoutTimeNull_WhenNull() {
ClientLoginLog log = new ClientLoginLog();
log.setLogoutTime(null);
assertTrue(log.isLogoutTimeNull());
}
@Test
void testIsLogoutTimeNull_WhenNotNull() {
ClientLoginLog log = new ClientLoginLog();
LocalDateTime logoutTime = LocalDateTime.now();
log.setLogoutTime(logoutTime);
assertFalse(log.isLogoutTimeNull());
}
@Test
void testConstructor_GeneratesId() {
ClientLoginLog log1 = new ClientLoginLog(TEST_CLIENT_USER_ID, TEST_IP_ADDRESS);
ClientLoginLog log2 = new ClientLoginLog(TEST_CLIENT_USER_ID, TEST_IP_ADDRESS);
assertNotNull(log1.getId());
assertNotNull(log2.getId());
assertNotEquals(log1.getId(), log2.getId());
}
@Test
void testConstructor_SetsLoginTimeToNow() {
LocalDateTime before = LocalDateTime.now();
ClientLoginLog log = new ClientLoginLog(TEST_CLIENT_USER_ID, TEST_IP_ADDRESS);
LocalDateTime after = LocalDateTime.now();
assertNotNull(log.getLoginTime());
assertTrue(log.getLoginTime().isAfter(before.minusSeconds(1)));
assertTrue(log.getLoginTime().isBefore(after.plusSeconds(1)));
}
}
@@ -0,0 +1,209 @@
package io.destiny.client.core.domain;
import io.destiny.common.primitive.PhoneNumber;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class ClientUserTest {
private static final Long TEST_ID = 12345L;
private static final String TEST_USERNAME = "testuser";
private static final String TEST_PASSWORD = "password123";
private static final String TEST_WECHAT_OPEN_ID = "wx_open_id_123";
private static final String TEST_WECHAT_UNION_ID = "wx_union_id_456";
private static final String TEST_DOUYIN_OPEN_ID = "dy_open_id_789";
private static final String TEST_DOUYIN_UNION_ID = "dy_union_id_012";
private static final String TEST_GENDER = "male";
private static final String TEST_NICKNAME = "测试用户";
private static final String TEST_AVATAR_URL = "https://example.com/avatar.jpg";
@Test
void testConstructor_DefaultValues() {
ClientUser user = new ClientUser();
assertNull(user.getId());
assertNull(user.getUsername());
assertNull(user.getPassword());
assertNull(user.getEmail());
assertNull(user.getPhone());
assertNull(user.getGender());
assertNull(user.getBirthTime());
assertNull(user.getWechatOpenId());
assertNull(user.getWechatUnionId());
assertNull(user.getDouyinOpenId());
assertNull(user.getDouyinUnionId());
assertNull(user.getPhoneVerified());
assertNull(user.getNickname());
assertNull(user.getAvatarUrl());
assertNull(user.getCreatedAt());
assertNull(user.getUpdatedAt());
assertNull(user.getDeletedAt());
assertNull(user.getLoginLogs());
}
@Test
void testGettersAndSetters() {
ClientUser user = new ClientUser();
user.setId(TEST_ID);
user.setUsername(TEST_USERNAME);
user.setPassword(TEST_PASSWORD);
user.setGender(TEST_GENDER);
user.setWechatOpenId(TEST_WECHAT_OPEN_ID);
user.setWechatUnionId(TEST_WECHAT_UNION_ID);
user.setDouyinOpenId(TEST_DOUYIN_OPEN_ID);
user.setDouyinUnionId(TEST_DOUYIN_UNION_ID);
user.setPhoneVerified(true);
user.setNickname(TEST_NICKNAME);
user.setAvatarUrl(TEST_AVATAR_URL);
LocalDateTime testBirthTime = LocalDateTime.of(1990, 1, 1, 0, 0);
user.setBirthTime(testBirthTime);
LocalDateTime testCreatedAt = LocalDateTime.now().minusDays(1);
LocalDateTime testUpdatedAt = LocalDateTime.now().minusHours(1);
LocalDateTime testDeletedAt = LocalDateTime.now();
user.setCreatedAt(testCreatedAt);
user.setUpdatedAt(testUpdatedAt);
user.setDeletedAt(testDeletedAt);
assertEquals(TEST_ID, user.getId());
assertEquals(TEST_USERNAME, user.getUsername());
assertEquals(TEST_PASSWORD, user.getPassword());
assertEquals(TEST_GENDER, user.getGender());
assertEquals(TEST_WECHAT_OPEN_ID, user.getWechatOpenId());
assertEquals(TEST_WECHAT_UNION_ID, user.getWechatUnionId());
assertEquals(TEST_DOUYIN_OPEN_ID, user.getDouyinOpenId());
assertEquals(TEST_DOUYIN_UNION_ID, user.getDouyinUnionId());
assertTrue(user.getPhoneVerified());
assertEquals(TEST_NICKNAME, user.getNickname());
assertEquals(TEST_AVATAR_URL, user.getAvatarUrl());
assertEquals(testBirthTime, user.getBirthTime());
assertEquals(testCreatedAt, user.getCreatedAt());
assertEquals(testUpdatedAt, user.getUpdatedAt());
assertEquals(testDeletedAt, user.getDeletedAt());
}
@Test
void testSetPhone_WithPhoneNumber() {
ClientUser user = new ClientUser();
PhoneNumber phoneNumber = PhoneNumber.of("13800138000");
user.setPhone(phoneNumber);
assertEquals(phoneNumber, user.getPhone());
}
@Test
void testSetPhone_WithNull() {
ClientUser user = new ClientUser();
user.setPhone(null);
assertNull(user.getPhone());
}
@Test
void testGenerateId_SetsUniqueId() {
ClientUser user = new ClientUser();
user.generateId();
assertNotNull(user.getId());
assertTrue(user.getId() > 0);
}
@Test
void testGenerateId_GeneratesDifferentIds() {
ClientUser user1 = new ClientUser();
ClientUser user2 = new ClientUser();
user1.generateId();
user2.generateId();
assertNotNull(user1.getId());
assertNotNull(user2.getId());
assertNotEquals(user1.getId(), user2.getId());
}
@Test
void testDelete_SetsDeletedAt() {
ClientUser user = new ClientUser();
assertNull(user.getDeletedAt());
user.delete();
assertNotNull(user.getDeletedAt());
assertTrue(user.getDeletedAt().isBefore(LocalDateTime.now().plusSeconds(1)));
assertTrue(user.getDeletedAt().isAfter(LocalDateTime.now().minusSeconds(1)));
}
@Test
void testDelete_CanBeCalledMultipleTimes() {
ClientUser user = new ClientUser();
user.delete();
LocalDateTime firstDeletedAt = user.getDeletedAt();
user.delete();
LocalDateTime secondDeletedAt = user.getDeletedAt();
assertNotNull(secondDeletedAt);
assertNotEquals(firstDeletedAt, secondDeletedAt);
}
@Test
void testPhoneVerified_DefaultValue() {
ClientUser user = new ClientUser();
assertNull(user.getPhoneVerified());
}
@Test
void testPhoneVerified_SetToTrue() {
ClientUser user = new ClientUser();
user.setPhoneVerified(true);
assertTrue(user.getPhoneVerified());
}
@Test
void testPhoneVerified_SetToFalse() {
ClientUser user = new ClientUser();
user.setPhoneVerified(false);
assertFalse(user.getPhoneVerified());
}
@Test
void testDeletedAt_DefaultValue() {
ClientUser user = new ClientUser();
assertNull(user.getDeletedAt());
}
@Test
void testDeleted_AfterDelete() {
ClientUser user = new ClientUser();
user.delete();
assertNotNull(user.getDeletedAt());
}
@Test
void testLoginLogs_DefaultValue() {
ClientUser user = new ClientUser();
assertNull(user.getLoginLogs());
}
@Test
void testSetLoginLogs_WithEmptyList() {
ClientUser user = new ClientUser();
user.setLoginLogs(List.of());
assertNotNull(user.getLoginLogs());
assertTrue(user.getLoginLogs().isEmpty());
}
}
@@ -0,0 +1,163 @@
package io.destiny.client.core.domain;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class SmsVerificationCodeTest {
private static final String TEST_PHONE = "13800138000";
private static final String TEST_CODE = "123456";
private static final String TEST_TYPE = "login";
@Test
void testConstructor_ValidInput_Success() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertNotNull(code.getId());
assertEquals(TEST_PHONE, code.getPhone());
assertEquals(TEST_CODE, code.getCode());
assertEquals(TEST_TYPE, code.getType());
assertEquals(expireTime, code.getExpireTime());
assertNotNull(code.getCreatedAt());
assertNotNull(code.getUpdatedAt());
assertFalse(code.isVerified());
assertEquals(0, code.getVerifyCount());
}
@Test
void testConstructor_GeneratesUniqueId() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code1 = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
SmsVerificationCode code2 = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertNotNull(code1.getId());
assertNotNull(code2.getId());
assertNotEquals(code1.getId(), code2.getId());
}
@Test
void testMarkAsVerified_UpdatesStatusAndTimestamp() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
LocalDateTime originalUpdatedAt = code.getUpdatedAt();
code.markAsVerified();
assertTrue(code.isVerified());
assertTrue(code.getUpdatedAt().isAfter(originalUpdatedAt) || code.getUpdatedAt().isEqual(originalUpdatedAt));
}
@Test
void testIncrementVerifyCount_FromZero() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
code.incrementVerifyCount();
assertEquals(1, code.getVerifyCount());
}
@Test
void testIncrementVerifyCount_MultipleTimes() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
code.incrementVerifyCount();
code.incrementVerifyCount();
code.incrementVerifyCount();
assertEquals(3, code.getVerifyCount());
}
@Test
void testIncrementVerifyCount_UpdatesTimestamp() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
LocalDateTime originalUpdatedAt = code.getUpdatedAt();
code.incrementVerifyCount();
assertTrue(code.getUpdatedAt().isAfter(originalUpdatedAt) || code.getUpdatedAt().isEqual(originalUpdatedAt));
}
@Test
void testIsExpired_WithFutureExpireTime() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertFalse(code.isExpired());
}
@Test
void testIsExpired_WithPastExpireTime() {
LocalDateTime expireTime = LocalDateTime.now().minusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertTrue(code.isExpired());
}
@Test
void testIsExpired_WithCurrentTime() {
LocalDateTime expireTime = LocalDateTime.now().plusSeconds(1);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertFalse(code.isExpired());
}
@Test
void testIsVerified_DefaultValue() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertFalse(code.isVerified());
}
@Test
void testIsVerified_AfterMarkAsVerified() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
code.markAsVerified();
assertTrue(code.isVerified());
}
@Test
void testGetVerifyCount_DefaultValue() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
assertEquals(0, code.getVerifyCount());
}
@Test
void testGetVerifyCount_AfterIncrements() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
code.incrementVerifyCount();
code.incrementVerifyCount();
assertEquals(2, code.getVerifyCount());
}
@Test
void testGettersAndSetters() {
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
SmsVerificationCode code = new SmsVerificationCode(TEST_PHONE, TEST_CODE, TEST_TYPE, expireTime);
Long testId = 12345L;
LocalDateTime testCreatedAt = LocalDateTime.now().minusHours(1);
LocalDateTime testUpdatedAt = LocalDateTime.now().minusMinutes(30);
code.setId(testId);
code.setCreatedAt(testCreatedAt);
code.setUpdatedAt(testUpdatedAt);
assertEquals(testId, code.getId());
assertEquals(testCreatedAt, code.getCreatedAt());
assertEquals(testUpdatedAt, code.getUpdatedAt());
}
}
@@ -0,0 +1,167 @@
package io.destiny.client.core.domain;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class UserBindingTest {
private static final Long TEST_ID = 12345L;
private static final Long TEST_USER_ID = 67890L;
private static final String TEST_PLATFORM = "wechat";
private static final String TEST_PLATFORM_OPEN_ID = "wx_open_id_123";
private static final String TEST_PLATFORM_UNION_ID = "wx_union_id_456";
@Test
void testConstructor_DefaultValues() {
UserBinding binding = new UserBinding();
assertNull(binding.getId());
assertNull(binding.getUserId());
assertNull(binding.getPlatform());
assertNull(binding.getPlatformOpenId());
assertNull(binding.getPlatformUnionId());
assertNull(binding.getCreatedAt());
assertNull(binding.getUpdatedAt());
assertNull(binding.getDeletedAt());
}
@Test
void testGettersAndSetters() {
UserBinding binding = new UserBinding();
binding.setId(TEST_ID);
binding.setUserId(TEST_USER_ID);
binding.setPlatform(TEST_PLATFORM);
binding.setPlatformOpenId(TEST_PLATFORM_OPEN_ID);
binding.setPlatformUnionId(TEST_PLATFORM_UNION_ID);
LocalDateTime testCreatedAt = LocalDateTime.now().minusDays(1);
LocalDateTime testUpdatedAt = LocalDateTime.now().minusHours(1);
LocalDateTime testDeletedAt = LocalDateTime.now();
binding.setCreatedAt(testCreatedAt);
binding.setUpdatedAt(testUpdatedAt);
binding.setDeletedAt(testDeletedAt);
assertEquals(TEST_ID, binding.getId());
assertEquals(TEST_USER_ID, binding.getUserId());
assertEquals(TEST_PLATFORM, binding.getPlatform());
assertEquals(TEST_PLATFORM_OPEN_ID, binding.getPlatformOpenId());
assertEquals(TEST_PLATFORM_UNION_ID, binding.getPlatformUnionId());
assertEquals(testCreatedAt, binding.getCreatedAt());
assertEquals(testUpdatedAt, binding.getUpdatedAt());
assertEquals(testDeletedAt, binding.getDeletedAt());
}
@Test
void testGenerateId_SetsUniqueId() {
UserBinding binding = new UserBinding();
binding.generateId();
assertNotNull(binding.getId());
assertTrue(binding.getId() > 0);
}
@Test
void testGenerateId_GeneratesDifferentIds() {
UserBinding binding1 = new UserBinding();
UserBinding binding2 = new UserBinding();
binding1.generateId();
binding2.generateId();
assertNotNull(binding1.getId());
assertNotNull(binding2.getId());
assertNotEquals(binding1.getId(), binding2.getId());
}
@Test
void testDelete_SetsDeletedAt() {
UserBinding binding = new UserBinding();
assertNull(binding.getDeletedAt());
binding.delete();
assertNotNull(binding.getDeletedAt());
assertTrue(binding.getDeletedAt().isBefore(LocalDateTime.now().plusSeconds(1)));
assertTrue(binding.getDeletedAt().isAfter(LocalDateTime.now().minusSeconds(1)));
}
@Test
void testDelete_CanBeCalledMultipleTimes() {
UserBinding binding = new UserBinding();
binding.delete();
LocalDateTime firstDeletedAt = binding.getDeletedAt();
binding.delete();
LocalDateTime secondDeletedAt = binding.getDeletedAt();
assertNotNull(secondDeletedAt);
assertNotEquals(firstDeletedAt, secondDeletedAt);
}
@Test
void testIsWechatPlatform_WhenWechat() {
UserBinding binding = new UserBinding();
binding.setPlatform("wechat");
assertTrue(binding.isWechatPlatform());
}
@Test
void testIsWechatPlatform_WhenDouyin() {
UserBinding binding = new UserBinding();
binding.setPlatform("douyin");
assertFalse(binding.isWechatPlatform());
}
@Test
void testIsWechatPlatform_WhenNull() {
UserBinding binding = new UserBinding();
binding.setPlatform(null);
assertFalse(binding.isWechatPlatform());
}
@Test
void testIsDouyinPlatform_WhenDouyin() {
UserBinding binding = new UserBinding();
binding.setPlatform("douyin");
assertTrue(binding.isDouyinPlatform());
}
@Test
void testIsDouyinPlatform_WhenWechat() {
UserBinding binding = new UserBinding();
binding.setPlatform("wechat");
assertFalse(binding.isDouyinPlatform());
}
@Test
void testIsDouyinPlatform_WhenNull() {
UserBinding binding = new UserBinding();
binding.setPlatform(null);
assertFalse(binding.isDouyinPlatform());
}
@Test
void testIsDeleted_WhenDeletedAtPresent() {
UserBinding binding = new UserBinding();
binding.setDeletedAt(LocalDateTime.now());
assertTrue(binding.isDeleted());
}
@Test
void testIsDeleted_WhenDeletedAtNull() {
UserBinding binding = new UserBinding();
binding.setDeletedAt(null);
assertFalse(binding.isDeleted());
}
}
@@ -0,0 +1,49 @@
package io.destiny.client.core.enums;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PlatformTypeTest {
@Test
void testGetCode() {
assertEquals("wechat", PlatformType.WECHAT.getCode());
assertEquals("douyin", PlatformType.DOUYIN.getCode());
}
@Test
void testGetDisplayName() {
assertEquals("微信小程序", PlatformType.WECHAT.getDisplayName());
assertEquals("抖音小程序", PlatformType.DOUYIN.getDisplayName());
}
@Test
void testFromCode() {
assertEquals(PlatformType.WECHAT, PlatformType.fromCode("wechat"));
assertEquals(PlatformType.DOUYIN, PlatformType.fromCode("douyin"));
}
@Test
void testFromCodeInvalid() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> PlatformType.fromCode("invalid_code")
);
assertTrue(exception.getMessage().contains("Unknown platform type"));
}
@Test
void testValues() {
PlatformType[] values = PlatformType.values();
assertEquals(2, values.length);
assertEquals(PlatformType.WECHAT, values[0]);
assertEquals(PlatformType.DOUYIN, values[1]);
}
@Test
void testValueOf() {
assertEquals(PlatformType.WECHAT, PlatformType.valueOf("WECHAT"));
assertEquals(PlatformType.DOUYIN, PlatformType.valueOf("DOUYIN"));
}
}
@@ -0,0 +1,67 @@
package io.destiny.client.core.enums;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SmsCodeTypeTest {
@Test
void testGetCode() {
assertEquals("login", SmsCodeType.LOGIN.getCode());
assertEquals("register", SmsCodeType.REGISTER.getCode());
assertEquals("bind", SmsCodeType.BIND.getCode());
assertEquals("reset_password", SmsCodeType.RESET_PASSWORD.getCode());
}
@Test
void testGetDisplayName() {
assertEquals("登录验证码", SmsCodeType.LOGIN.getDisplayName());
assertEquals("注册验证码", SmsCodeType.REGISTER.getDisplayName());
assertEquals("绑定验证码", SmsCodeType.BIND.getDisplayName());
assertEquals("重置密码验证码", SmsCodeType.RESET_PASSWORD.getDisplayName());
}
@Test
void testGetTemplateCode() {
assertEquals("SMS_123456789", SmsCodeType.LOGIN.getTemplateCode());
assertEquals("SMS_123456790", SmsCodeType.REGISTER.getTemplateCode());
assertEquals("SMS_123456791", SmsCodeType.BIND.getTemplateCode());
assertEquals("SMS_123456792", SmsCodeType.RESET_PASSWORD.getTemplateCode());
}
@Test
void testFromCode() {
assertEquals(SmsCodeType.LOGIN, SmsCodeType.fromCode("login"));
assertEquals(SmsCodeType.REGISTER, SmsCodeType.fromCode("register"));
assertEquals(SmsCodeType.BIND, SmsCodeType.fromCode("bind"));
assertEquals(SmsCodeType.RESET_PASSWORD, SmsCodeType.fromCode("reset_password"));
}
@Test
void testFromCodeInvalid() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> SmsCodeType.fromCode("invalid_code")
);
assertTrue(exception.getMessage().contains("Unknown SMS code type"));
}
@Test
void testValues() {
SmsCodeType[] values = SmsCodeType.values();
assertEquals(4, values.length);
assertEquals(SmsCodeType.LOGIN, values[0]);
assertEquals(SmsCodeType.REGISTER, values[1]);
assertEquals(SmsCodeType.BIND, values[2]);
assertEquals(SmsCodeType.RESET_PASSWORD, values[3]);
}
@Test
void testValueOf() {
assertEquals(SmsCodeType.LOGIN, SmsCodeType.valueOf("LOGIN"));
assertEquals(SmsCodeType.REGISTER, SmsCodeType.valueOf("REGISTER"));
assertEquals(SmsCodeType.BIND, SmsCodeType.valueOf("BIND"));
assertEquals(SmsCodeType.RESET_PASSWORD, SmsCodeType.valueOf("RESET_PASSWORD"));
}
}
@@ -0,0 +1,130 @@
package io.destiny.client.core.exception;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ClientUserAuthExceptionCodeTest {
@Test
void testGetCode() {
assertEquals("CLIENT_AUTH_10001", ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD.getCode());
assertEquals("CLIENT_AUTH_10002", ClientUserAuthExceptionCode.CLIENT_INVALID_PLATFORM.getCode());
assertEquals("CLIENT_AUTH_10003", ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE.getCode());
assertEquals("CLIENT_AUTH_10004", ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED.getCode());
assertEquals("CLIENT_AUTH_10005", ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE.getCode());
assertEquals("CLIENT_AUTH_10006", ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED.getCode());
assertEquals("CLIENT_AUTH_10007", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXPIRED.getCode());
assertEquals("CLIENT_AUTH_10008", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID.getCode());
assertEquals("CLIENT_AUTH_10009", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_USED.getCode());
assertEquals("CLIENT_AUTH_10010", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXCEEDED.getCode());
assertEquals("CLIENT_AUTH_10011", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST.getCode());
assertEquals("CLIENT_AUTH_10012", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED.getCode());
assertEquals("CLIENT_AUTH_10013", ClientUserAuthExceptionCode.CLIENT_USER_NOT_FOUND.getCode());
assertEquals("CLIENT_AUTH_10014", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_ALREADY_BOUND.getCode());
assertEquals("CLIENT_AUTH_10015", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_BIND_FAILED.getCode());
assertEquals("CLIENT_AUTH_10016", ClientUserAuthExceptionCode.CLIENT_PHONE_NOT_VERIFIED.getCode());
assertEquals("CLIENT_AUTH_10017", ClientUserAuthExceptionCode.CLIENT_AUTO_REGISTER_FAILED.getCode());
assertEquals("CLIENT_AUTH_10018", ClientUserAuthExceptionCode.CLIENT_LOGIN_TYPE_INVALID.getCode());
assertEquals("CLIENT_AUTH_10019", ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED.getCode());
assertEquals("CLIENT_AUTH_10020", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED.getCode());
}
@Test
void testGetDisplayName() {
assertEquals("用户名或密码错误", ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD.getDisplayName());
assertEquals("平台标识无效", ClientUserAuthExceptionCode.CLIENT_INVALID_PLATFORM.getDisplayName());
assertEquals("微信授权码无效", ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE.getDisplayName());
assertEquals("微信授权失败", ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED.getDisplayName());
assertEquals("抖音授权码无效", ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE.getDisplayName());
assertEquals("抖音授权失败", ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED.getDisplayName());
assertEquals("验证码已过期", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXPIRED.getDisplayName());
assertEquals("验证码错误", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID.getDisplayName());
assertEquals("验证码已使用", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_USED.getDisplayName());
assertEquals("验证码验证次数过多", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXCEEDED.getDisplayName());
assertEquals("验证码发送频率过高", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST.getDisplayName());
assertEquals("验证码发送次数超限", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED.getDisplayName());
assertEquals("用户不存在", ClientUserAuthExceptionCode.CLIENT_USER_NOT_FOUND.getDisplayName());
assertEquals("账号已绑定", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_ALREADY_BOUND.getDisplayName());
assertEquals("账号绑定失败", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_BIND_FAILED.getDisplayName());
assertEquals("手机号未验证", ClientUserAuthExceptionCode.CLIENT_PHONE_NOT_VERIFIED.getDisplayName());
assertEquals("自动注册失败", ClientUserAuthExceptionCode.CLIENT_AUTO_REGISTER_FAILED.getDisplayName());
assertEquals("登录类型无效", ClientUserAuthExceptionCode.CLIENT_LOGIN_TYPE_INVALID.getDisplayName());
assertEquals("登录失败", ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED.getDisplayName());
assertEquals("账号已锁定", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED.getDisplayName());
}
@Test
void testGetHttpCode() {
assertEquals("401", ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_INVALID_PLATFORM.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXPIRED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_USED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXCEEDED.getHttpCode());
assertEquals("429", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST.getHttpCode());
assertEquals("429", ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED.getHttpCode());
assertEquals("404", ClientUserAuthExceptionCode.CLIENT_USER_NOT_FOUND.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_ALREADY_BOUND.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_BIND_FAILED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_PHONE_NOT_VERIFIED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_AUTO_REGISTER_FAILED.getHttpCode());
assertEquals("400", ClientUserAuthExceptionCode.CLIENT_LOGIN_TYPE_INVALID.getHttpCode());
assertEquals("401", ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED.getHttpCode());
assertEquals("403", ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED.getHttpCode());
}
@Test
void testValues() {
ClientUserAuthExceptionCode[] values = ClientUserAuthExceptionCode.values();
assertEquals(20, values.length);
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD, values[0]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_PLATFORM, values[1]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE, values[2]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED, values[3]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE, values[4]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED, values[5]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXPIRED, values[6]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID, values[7]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_USED, values[8]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXCEEDED, values[9]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST, values[10]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED, values[11]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_USER_NOT_FOUND, values[12]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_ALREADY_BOUND, values[13]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_BIND_FAILED, values[14]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_PHONE_NOT_VERIFIED, values[15]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_AUTO_REGISTER_FAILED, values[16]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_LOGIN_TYPE_INVALID, values[17]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED, values[18]);
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED, values[19]);
}
@Test
void testValueOf() {
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD, ClientUserAuthExceptionCode.valueOf("CLIENT_INVALID_USERNAME_OR_PASSWORD"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_PLATFORM, ClientUserAuthExceptionCode.valueOf("CLIENT_INVALID_PLATFORM"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE, ClientUserAuthExceptionCode.valueOf("CLIENT_INVALID_WECHAT_CODE"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_WECHAT_AUTH_FAILED, ClientUserAuthExceptionCode.valueOf("CLIENT_WECHAT_AUTH_FAILED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE, ClientUserAuthExceptionCode.valueOf("CLIENT_INVALID_DOUYIN_CODE"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_DOUYIN_AUTH_FAILED, ClientUserAuthExceptionCode.valueOf("CLIENT_DOUYIN_AUTH_FAILED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXPIRED, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_EXPIRED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_INVALID"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_USED, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_USED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_EXCEEDED, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_EXCEEDED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_SEND_TOO_FAST"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED, ClientUserAuthExceptionCode.valueOf("CLIENT_SMS_CODE_SEND_EXCEEDED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_USER_NOT_FOUND, ClientUserAuthExceptionCode.valueOf("CLIENT_USER_NOT_FOUND"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_ALREADY_BOUND, ClientUserAuthExceptionCode.valueOf("CLIENT_ACCOUNT_ALREADY_BOUND"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_BIND_FAILED, ClientUserAuthExceptionCode.valueOf("CLIENT_ACCOUNT_BIND_FAILED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_PHONE_NOT_VERIFIED, ClientUserAuthExceptionCode.valueOf("CLIENT_PHONE_NOT_VERIFIED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_AUTO_REGISTER_FAILED, ClientUserAuthExceptionCode.valueOf("CLIENT_AUTO_REGISTER_FAILED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_LOGIN_TYPE_INVALID, ClientUserAuthExceptionCode.valueOf("CLIENT_LOGIN_TYPE_INVALID"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED, ClientUserAuthExceptionCode.valueOf("CLIENT_LOGIN_FAILED"));
assertEquals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED, ClientUserAuthExceptionCode.valueOf("CLIENT_ACCOUNT_LOCKED"));
}
}
@@ -0,0 +1,35 @@
package io.destiny.client.core.exception;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ClientUserExceptionCodeTest {
@Test
void testGetCode() {
assertEquals("CLIENT_USER_20001", ClientUserExceptionCode.CLIENT_USER_NOT_FOUND.getCode());
}
@Test
void testGetDisplayName() {
assertEquals("客户端用户不存在", ClientUserExceptionCode.CLIENT_USER_NOT_FOUND.getDisplayName());
}
@Test
void testGetHttpCode() {
assertEquals("500", ClientUserExceptionCode.CLIENT_USER_NOT_FOUND.getHttpCode());
}
@Test
void testValues() {
ClientUserExceptionCode[] values = ClientUserExceptionCode.values();
assertEquals(1, values.length);
assertEquals(ClientUserExceptionCode.CLIENT_USER_NOT_FOUND, values[0]);
}
@Test
void testValueOf() {
assertEquals(ClientUserExceptionCode.CLIENT_USER_NOT_FOUND, ClientUserExceptionCode.valueOf("CLIENT_USER_NOT_FOUND"));
}
}
@@ -0,0 +1,157 @@
package io.destiny.client.core.exception;
import io.destiny.common.exception.ApplicationException;
import io.destiny.common.exception.ExceptionCode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
import reactor.test.StepVerifier;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(MockitoExtension.class)
@DisplayName("GlobalExceptionHandler 测试")
class GlobalExceptionHandlerTest {
private GlobalExceptionHandler globalExceptionHandler;
private ServerWebExchange exchange;
@BeforeEach
void setUp() {
globalExceptionHandler = new GlobalExceptionHandler();
exchange = MockServerWebExchange.from(org.springframework.mock.http.server.reactive.MockServerHttpRequest
.get("/api/test").accept(MediaType.APPLICATION_JSON));
}
@Test
@DisplayName("处理 ApplicationException - 包含 exceptionCode")
void testHandleApplicationExceptionWithCode() {
ApplicationException exception = new ApplicationException(
ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID);
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 ApplicationException - exceptionCode 为 null,exceptionMessage 不为 null")
void testHandleApplicationExceptionWithNullCodeAndMessage() {
ApplicationException exception = new ApplicationException((ExceptionCode) null,
new Object[] { "Custom error message" });
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 ApplicationException - exceptionCode 不为 null,arguments 为 null")
void testHandleApplicationExceptionWithCodeAndNullMessage() {
ApplicationException exception = new ApplicationException(
ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID,
(Object[]) null);
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 ApplicationException - exceptionCode 和 arguments 都为 null")
void testHandleApplicationExceptionWithNullCodeAndNullMessage() {
ApplicationException exception = new ApplicationException((ExceptionCode) null, (Object[]) null);
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 IllegalArgumentException")
void testHandleIllegalArgumentException() {
IllegalArgumentException exception = new IllegalArgumentException("Invalid argument");
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理通用 Exception")
void testHandleGenericException() {
Exception exception = new Exception("Unexpected error");
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理未知 Throwable(非 Exception)")
void testHandleUnknownException() {
Throwable throwable = new Throwable("Unknown error");
StepVerifier.create(globalExceptionHandler.handleException(throwable, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 RuntimeException(继承自 Exception)")
void testHandleRuntimeException() {
RuntimeException exception = new RuntimeException("Runtime error");
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 NullPointerException(继承自 RuntimeException)")
void testHandleNullPointerException() {
NullPointerException exception = new NullPointerException("Null pointer");
StepVerifier.create(globalExceptionHandler.handleException(exception, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
@Test
@DisplayName("处理 Error(非 Exception)")
void testHandleError() {
Error error = new Error("Fatal error");
StepVerifier.create(globalExceptionHandler.handleException(error, exchange))
.assertNext(response -> {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.statusCode());
})
.verifyComplete();
}
}
@@ -0,0 +1,239 @@
package io.destiny.client.core.service;
import io.destiny.client.core.domain.ClientLoginLog;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.domain.query.ClientUserLogin;
import io.destiny.client.core.repository.IClientLoginLogRepository;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.client.dto.ClientLoginResponse;
import io.destiny.client.security.JwtTokenProvider;
import io.destiny.common.exception.ApplicationException;
import io.destiny.common.primitive.EmailAddress;
import io.destiny.common.primitive.IpAddress;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.password.PasswordEncoder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ClientUserAuthServiceTest {
@Mock
private IClientUserRepository clientUserRepository;
@Mock
private IClientLoginLogRepository clientLoginLogRepository;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private JwtTokenProvider jwtTokenProvider;
@InjectMocks
private ClientUserAuthService clientUserAuthService;
private ClientUser testUser;
private ClientUserLogin testLogin;
@BeforeEach
void setUp() {
testUser = new ClientUser();
testUser.setId(1L);
testUser.setUsername("testuser");
testUser.setPassword("encodedPassword");
testUser.setEmail(EmailAddress.of("test@example.com"));
testLogin = new ClientUserLogin();
testLogin.setUsername("testuser");
testLogin.setPassword("rawPassword");
testLogin.setIpAddress(IpAddress.of("127.0.0.1"));
}
@Test
void testRegister_Success() {
ClientUser newUser = new ClientUser();
newUser.setUsername("newuser");
newUser.setPassword("rawPassword");
newUser.setEmail(EmailAddress.of("new@example.com"));
when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword");
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(testUser));
Mono<ClientUser> result = clientUserAuthService.register(newUser);
assertNotNull(result);
ClientUser registeredUser = result.block();
assertEquals("testuser", registeredUser.getUsername());
assertEquals("encodedPassword", registeredUser.getPassword());
verify(passwordEncoder, times(1)).encode(anyString());
verify(clientUserRepository, times(1)).save(any(ClientUser.class));
}
@Test
void testLogin_Success() {
when(clientUserRepository.findByUsername(anyString())).thenReturn(Mono.just(testUser));
when(passwordEncoder.matches(anyString(), anyString())).thenReturn(true);
when(clientLoginLogRepository.save(any(ClientLoginLog.class))).thenReturn(Mono.just(new ClientLoginLog()));
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
Mono<ClientLoginResponse> result = clientUserAuthService.login(testLogin);
assertNotNull(result);
ClientLoginResponse response = result.block();
assertNotNull(response);
assertEquals("test-token", response.getToken());
verify(clientUserRepository, times(1)).findByUsername(anyString());
verify(passwordEncoder, times(1)).matches(anyString(), anyString());
verify(clientLoginLogRepository, times(1)).save(any(ClientLoginLog.class));
verify(jwtTokenProvider, times(1)).generateToken(anyLong(), anyString());
}
@Test
void testLogin_InvalidPassword() {
when(clientUserRepository.findByUsername(anyString())).thenReturn(Mono.just(testUser));
when(passwordEncoder.matches(anyString(), anyString())).thenReturn(false);
Mono<ClientLoginResponse> result = clientUserAuthService.login(testLogin);
assertThrows(ApplicationException.class, () -> result.block());
verify(clientUserRepository, times(1)).findByUsername(anyString());
verify(passwordEncoder, times(1)).matches(anyString(), anyString());
verify(clientLoginLogRepository, never()).save(any(ClientLoginLog.class));
verify(jwtTokenProvider, never()).generateToken(anyLong(), anyString());
}
@Test
void testLogin_UserNotFound() {
when(clientUserRepository.findByUsername(anyString())).thenReturn(Mono.empty());
Mono<ClientLoginResponse> result = clientUserAuthService.login(testLogin);
assertThrows(ApplicationException.class, () -> result.block());
verify(clientUserRepository, times(1)).findByUsername(anyString());
verify(passwordEncoder, never()).matches(anyString(), anyString());
}
@Test
void testRefreshLoginToken_Success() {
String oldToken = "old-test-token";
when(jwtTokenProvider.getUserIdFromToken(anyString())).thenReturn(1L);
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.just(testUser));
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("new-test-token");
Mono<ClientLoginResponse> result = clientUserAuthService.refreshLoginToken(oldToken);
assertNotNull(result);
ClientLoginResponse response = result.block();
assertNotNull(response);
assertEquals("new-test-token", response.getToken());
verify(jwtTokenProvider, times(1)).getUserIdFromToken(anyString());
verify(clientUserRepository, times(1)).findById(anyLong());
verify(jwtTokenProvider, times(1)).generateToken(anyLong(), anyString());
}
@Test
void testRefreshLoginToken_InvalidToken() {
String oldToken = "invalid-token";
when(jwtTokenProvider.getUserIdFromToken(anyString())).thenReturn(null);
Mono<ClientLoginResponse> result = clientUserAuthService.refreshLoginToken(oldToken);
assertThrows(ApplicationException.class, () -> result.block());
verify(jwtTokenProvider, times(1)).getUserIdFromToken(anyString());
verify(clientUserRepository, never()).findById(anyLong());
}
@Test
void testRefreshLoginToken_UserNotFound() {
String oldToken = "old-test-token";
when(jwtTokenProvider.getUserIdFromToken(anyString())).thenReturn(1L);
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.empty());
Mono<ClientLoginResponse> result = clientUserAuthService.refreshLoginToken(oldToken);
assertThrows(ApplicationException.class, () -> result.block());
verify(jwtTokenProvider, times(1)).getUserIdFromToken(anyString());
verify(clientUserRepository, times(1)).findById(anyLong());
}
@Test
void testLogout_Success() {
Long userId = 1L;
ClientLoginLog loginLog = new ClientLoginLog();
loginLog.setLogoutTime(null);
when(clientLoginLogRepository.findByClientUserId(anyLong())).thenReturn(Flux.just(loginLog));
when(clientLoginLogRepository.save(any(ClientLoginLog.class))).thenReturn(Mono.just(loginLog));
Mono<Void> result = clientUserAuthService.logout(userId);
assertNotNull(result);
result.block();
verify(clientLoginLogRepository, times(1)).findByClientUserId(anyLong());
verify(clientLoginLogRepository, times(1)).save(any(ClientLoginLog.class));
}
@Test
void testLogout_NoActiveSession() {
Long userId = 1L;
when(clientLoginLogRepository.findByClientUserId(anyLong())).thenReturn(Flux.empty());
Mono<Void> result = clientUserAuthService.logout(userId);
assertNotNull(result);
result.block();
verify(clientLoginLogRepository, times(1)).findByClientUserId(anyLong());
verify(clientLoginLogRepository, never()).save(any(ClientLoginLog.class));
}
@Test
void testCheckLoginStatus_Active() {
Long userId = 1L;
ClientLoginLog loginLog = new ClientLoginLog();
loginLog.setLogoutTime(null);
when(clientLoginLogRepository.findByClientUserId(anyLong())).thenReturn(Flux.just(loginLog));
Mono<Boolean> result = clientUserAuthService.checkLoginStatus(userId);
assertNotNull(result);
Boolean isActive = result.block();
assertTrue(isActive);
verify(clientLoginLogRepository, times(1)).findByClientUserId(anyLong());
}
@Test
void testCheckLoginStatus_Inactive() {
Long userId = 1L;
when(clientLoginLogRepository.findByClientUserId(anyLong())).thenReturn(Flux.empty());
Mono<Boolean> result = clientUserAuthService.checkLoginStatus(userId);
assertNotNull(result);
Boolean isActive = result.block();
assertFalse(isActive);
verify(clientLoginLogRepository, times(1)).findByClientUserId(anyLong());
}
}
@@ -0,0 +1,189 @@
package io.destiny.client.core.service;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.domain.query.ClientUserQuery;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.common.exception.ApplicationException;
import io.destiny.common.primitive.EmailAddress;
import io.destiny.common.request.PageQuery;
import io.destiny.common.response.PageModel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ClientUserServiceTest {
@Mock
private IClientUserRepository clientUserRepository;
@InjectMocks
private ClientUserService clientUserService;
private ClientUser testUser;
@BeforeEach
void setUp() {
testUser = new ClientUser();
testUser.setId(1L);
testUser.setUsername("testuser");
testUser.setPassword("password");
testUser.setEmail(EmailAddress.of("test@example.com"));
testUser.setCreatedAt(LocalDateTime.now());
}
@Test
void testSave_Success() {
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(testUser));
Mono<ClientUser> result = clientUserService.save(testUser);
assertNotNull(result);
ClientUser savedUser = result.block();
assertEquals(1L, savedUser.getId());
assertEquals("testuser", savedUser.getUsername());
verify(clientUserRepository, times(1)).save(any(ClientUser.class));
}
@Test
void testUpdate_Success() {
ClientUser updateUser = new ClientUser();
updateUser.setId(1L);
updateUser.setUsername("updateduser");
updateUser.setPassword("newpassword");
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.just(testUser));
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(updateUser));
Mono<ClientUser> result = clientUserService.update(updateUser);
assertNotNull(result);
ClientUser updatedUser = result.block();
assertEquals("updateduser", updatedUser.getUsername());
verify(clientUserRepository, times(1)).findById(anyLong());
verify(clientUserRepository, times(1)).save(any(ClientUser.class));
}
@Test
void testUpdate_UserNotFound() {
ClientUser updateUser = new ClientUser();
updateUser.setId(999L);
updateUser.setUsername("updateduser");
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.empty());
Mono<ClientUser> result = clientUserService.update(updateUser);
assertThrows(ApplicationException.class, () -> result.block());
verify(clientUserRepository, times(1)).findById(anyLong());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testDeleteById_Success() {
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.just(testUser));
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(testUser));
Mono<Void> result = clientUserService.deleteById(1L);
assertNotNull(result);
result.block();
assertNotNull(testUser.getDeletedAt());
verify(clientUserRepository, times(1)).findById(anyLong());
verify(clientUserRepository, times(1)).save(any(ClientUser.class));
}
@Test
void testDeleteById_UserNotFound() {
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.empty());
Mono<Void> result = clientUserService.deleteById(999L);
assertThrows(ApplicationException.class, () -> result.block());
verify(clientUserRepository, times(1)).findById(anyLong());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testFindById_Success() {
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.just(testUser));
Mono<ClientUser> result = clientUserService.findById(1L);
assertNotNull(result);
ClientUser foundUser = result.block();
assertEquals(1L, foundUser.getId());
assertEquals("testuser", foundUser.getUsername());
verify(clientUserRepository, times(1)).findById(anyLong());
}
@Test
void testFindById_NotFound() {
when(clientUserRepository.findById(anyLong())).thenReturn(Mono.empty());
Mono<ClientUser> result = clientUserService.findById(999L);
assertNotNull(result);
ClientUser foundUser = result.block();
assertNull(foundUser);
verify(clientUserRepository, times(1)).findById(anyLong());
}
@Test
void testFindByPage_Success() {
ClientUserQuery query = new ClientUserQuery();
PageQuery pageQuery = new PageQuery(0, 10);
PageModel<ClientUser> pageModel = new PageModel<>(1L, Collections.singletonList(testUser));
when(clientUserRepository.findByQueryWithPagination(any(ClientUserQuery.class), any(PageQuery.class)))
.thenReturn(Mono.just(pageModel));
Mono<PageModel<ClientUser>> result = clientUserService.findByPage(query, pageQuery);
assertNotNull(result);
PageModel<ClientUser> resultPage = result.block();
assertEquals(1, resultPage.getData().size());
assertEquals(1L, resultPage.getCount());
verify(clientUserRepository, times(1)).findByQueryWithPagination(any(ClientUserQuery.class), any(PageQuery.class));
}
@Test
void testFindByPage_EmptyResult() {
ClientUserQuery query = new ClientUserQuery();
PageQuery pageQuery = new PageQuery(0, 10);
PageModel<ClientUser> pageModel = new PageModel<>(0L, Collections.emptyList());
when(clientUserRepository.findByQueryWithPagination(any(ClientUserQuery.class), any(PageQuery.class)))
.thenReturn(Mono.just(pageModel));
Mono<PageModel<ClientUser>> result = clientUserService.findByPage(query, pageQuery);
assertNotNull(result);
PageModel<ClientUser> resultPage = result.block();
assertTrue(resultPage.getData().isEmpty());
assertEquals(0L, resultPage.getCount());
verify(clientUserRepository, times(1)).findByQueryWithPagination(any(ClientUserQuery.class), any(PageQuery.class));
}
}
@@ -0,0 +1,344 @@
package io.destiny.client.core.service;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.github.benmanes.caffeine.cache.Cache;
import io.destiny.client.config.AliyunSmsConfig;
import io.destiny.client.core.domain.SmsVerificationCode;
import io.destiny.client.core.enums.SmsCodeType;
import io.destiny.client.core.exception.ClientUserAuthExceptionCode;
import io.destiny.client.core.repository.ISmsVerificationCodeRepository;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
@DisplayName("SmsService 测试")
class SmsServiceTest {
@Mock
private AliyunSmsConfig smsConfig;
@Mock
private ISmsVerificationCodeRepository smsVerificationCodeRepository;
@Mock
private Client smsClient;
private SmsService smsService;
@BeforeEach
void setUp() {
lenient().when(smsConfig.getSignName()).thenReturn("TestSign");
smsService = new SmsService(smsConfig, smsVerificationCodeRepository, smsClient);
}
@Test
@DisplayName("发送验证码 - 手机号为 null")
void testSendVerificationCodeWithNullPhone() {
StepVerifier.create(smsService.sendVerificationCode(null, SmsCodeType.LOGIN))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID)
.verify();
}
@Test
@DisplayName("发送验证码 - 手机号为空字符串")
void testSendVerificationCodeWithEmptyPhone() {
StepVerifier.create(smsService.sendVerificationCode("", SmsCodeType.LOGIN))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_INVALID)
.verify();
}
@Test
@DisplayName("发送验证码 - SmsCodeType 为 null")
void testSendVerificationCodeWithNullType() {
StepVerifier.create(smsService.sendVerificationCode("13800138000", null))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED)
.verify();
}
@Test
@DisplayName("发送验证码 - 新手机号成功发送")
void testSendVerificationCodeSuccess() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
SmsVerificationCode savedCode = new SmsVerificationCode();
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(savedCode));
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> {
assertNotNull(code);
assertEquals(6, code.length());
assertTrue(code.chars().allMatch(Character::isDigit));
})
.verifyComplete();
ArgumentCaptor<SmsVerificationCode> codeCaptor = ArgumentCaptor.forClass(SmsVerificationCode.class);
verify(smsVerificationCodeRepository).save(codeCaptor.capture());
SmsVerificationCode capturedCode = codeCaptor.getValue();
assertEquals(phone, capturedCode.getPhone());
assertEquals(type.getCode(), capturedCode.getType());
assertNotNull(capturedCode.getExpireTime());
assertTrue(capturedCode.getExpireTime().isAfter(LocalDateTime.now()));
}
@Test
@DisplayName("发送验证码 - 分钟速率限制已达到且未过期")
void testSendVerificationCodeMinuteRateLimitExceeded() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(new SmsVerificationCode()));
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_TOO_FAST)
.verify();
}
@Test
@DisplayName("发送验证码 - 分钟速率限制已达到但已过期")
void testSendVerificationCodeMinuteRateLimitExpired() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(new SmsVerificationCode()));
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
modifySendRecordExpireTime(phone, LocalDateTime.now().minusMinutes(1));
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
}
@Test
@DisplayName("发送验证码 - 日速率限制已达到且未过期")
void testSendVerificationCodeDayRateLimitExceeded() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(new SmsVerificationCode()));
for (int i = 0; i < 10; i++) {
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
modifySendRecordExpireTime(phone, LocalDateTime.now().minusMinutes(1));
}
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED)
.verify();
}
@Test
@DisplayName("发送验证码 - 日速率限制已达到但已过期")
void testSendVerificationCodeDayRateLimitExpired() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(new SmsVerificationCode()));
for (int i = 0; i < 10; i++) {
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
modifySendRecordExpireTime(phone, LocalDateTime.now().minusMinutes(1));
}
modifySendRecordDayExpireTime(phone, LocalDateTime.now().minusDays(1));
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
}
@Test
@DisplayName("发送验证码 - 阿里云短信发送失败")
void testSendVerificationCodeAliyunSendFailed() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("FAILED");
responseBody.setMessage("Invalid phone number");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED)
.verify();
}
@Test
@DisplayName("发送验证码 - 短信签名为 null")
void testSendVerificationCodeWithNullSignName() throws Exception {
String phone = "13800138000";
SmsCodeType type = SmsCodeType.LOGIN;
when(smsConfig.getSignName()).thenReturn(null);
smsService = new SmsService(smsConfig, smsVerificationCodeRepository, smsClient);
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.expectErrorMatches(throwable -> throwable instanceof ApplicationException &&
((ApplicationException) throwable)
.getExceptionCode() == ClientUserAuthExceptionCode.CLIENT_SMS_CODE_SEND_EXCEEDED)
.verify();
}
@Test
@DisplayName("发送验证码 - 不同的验证码类型")
void testSendVerificationCodeWithDifferentTypes() throws Exception {
SendSmsResponseBody responseBody = new SendSmsResponseBody();
responseBody.setCode("OK");
responseBody.setRequestId("test-request-id");
SendSmsResponse response = new SendSmsResponse();
response.setBody(responseBody);
when(smsClient.sendSms(any(SendSmsRequest.class))).thenReturn(response);
SmsVerificationCode savedCode = new SmsVerificationCode();
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class)))
.thenReturn(Mono.just(savedCode));
SmsCodeType[] types = { SmsCodeType.LOGIN, SmsCodeType.REGISTER, SmsCodeType.BIND,
SmsCodeType.RESET_PASSWORD };
for (SmsCodeType type : types) {
String phone = "1380013800" + type.getCode();
StepVerifier.create(smsService.sendVerificationCode(phone, type))
.assertNext(code -> assertNotNull(code))
.verifyComplete();
ArgumentCaptor<SmsVerificationCode> codeCaptor = ArgumentCaptor
.forClass(SmsVerificationCode.class);
verify(smsVerificationCodeRepository, atLeastOnce()).save(codeCaptor.capture());
SmsVerificationCode capturedCode = codeCaptor.getValue();
assertEquals(type.getCode(), capturedCode.getType());
}
}
private void modifySendRecordExpireTime(String phone, LocalDateTime newExpireTime) {
try {
Field cacheField = SmsService.class.getDeclaredField("sendRecords");
cacheField.setAccessible(true);
@SuppressWarnings("unchecked")
Cache<String, Object> cache = (Cache<String, Object>) cacheField.get(smsService);
Object sendRecord = cache.getIfPresent(phone);
if (sendRecord != null) {
Field minuteExpireTimeField = sendRecord.getClass()
.getDeclaredField("minuteExpireTime");
minuteExpireTimeField.setAccessible(true);
minuteExpireTimeField.set(sendRecord, newExpireTime);
}
} catch (Exception e) {
throw new RuntimeException("Failed to modify send record expire time", e);
}
}
private void modifySendRecordDayExpireTime(String phone, LocalDateTime newExpireTime) {
try {
Field cacheField = SmsService.class.getDeclaredField("sendRecords");
cacheField.setAccessible(true);
@SuppressWarnings("unchecked")
Cache<String, Object> cache = (Cache<String, Object>) cacheField.get(smsService);
Object sendRecord = cache.getIfPresent(phone);
if (sendRecord != null) {
Field dayExpireTimeField = sendRecord.getClass().getDeclaredField("dayExpireTime");
dayExpireTimeField.setAccessible(true);
dayExpireTimeField.set(sendRecord, newExpireTime);
}
} catch (Exception e) {
throw new RuntimeException("Failed to modify send record day expire time", e);
}
}
}
@@ -0,0 +1,324 @@
package io.destiny.client.core.strategy;
import io.destiny.client.client.DouyinMiniProgramClient;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.domain.UserBinding;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.client.core.repository.IUserBindingRepository;
import io.destiny.client.core.service.ClientUserAuthService;
import io.destiny.client.dto.DouyinLoginRequest;
import io.destiny.client.dto.LoginRequest;
import io.destiny.client.dto.WechatAuthResponse;
import io.destiny.client.security.JwtTokenProvider;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import static io.destiny.client.core.exception.ClientUserAuthExceptionCode.CLIENT_INVALID_DOUYIN_CODE;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class DouyinLoginStrategyTest {
@Mock
private ClientUserAuthService clientUserAuthService;
@Mock
private JwtTokenProvider jwtTokenProvider;
@Mock
private DouyinMiniProgramClient douyinClient;
@Mock
private IClientUserRepository clientUserRepository;
@Mock
private IUserBindingRepository userBindingRepository;
@InjectMocks
private DouyinLoginStrategy douyinLoginStrategy;
@BeforeEach
void setUp() {
}
@Test
void testGetLoginType() {
assertEquals("douyin", douyinLoginStrategy.getLoginType());
}
@Test
void testValidateRequestWithValidData() {
LoginRequest request = new LoginRequest();
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
StepVerifier.create(douyinLoginStrategy.validateRequest(request))
.expectNext(request)
.verifyComplete();
}
@Test
void testValidateRequestWithNullCode() {
LoginRequest request = new LoginRequest();
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode(null);
request.setData(douyinRequest);
StepVerifier.create(douyinLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode().equals(CLIENT_INVALID_DOUYIN_CODE))
.verify();
}
@Test
void testValidateRequestWithEmptyCode() {
LoginRequest request = new LoginRequest();
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("");
request.setData(douyinRequest);
StepVerifier.create(douyinLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode().equals(CLIENT_INVALID_DOUYIN_CODE))
.verify();
}
@Test
void testValidateRequestWithInvalidDataType() {
LoginRequest request = new LoginRequest();
request.setData("invalid_data");
StepVerifier.create(douyinLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode().equals(CLIENT_INVALID_DOUYIN_CODE))
.verify();
}
@Test
void testLoginSuccessWithExistingUserByOpenId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setDouyinOpenId("open_id_123");
when(douyinClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByDouyinOpenId("open_id_123")).thenReturn(Mono.just(user));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("douyin") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).findByDouyinUnionId(anyString());
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithExistingUserByUnionId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setDouyinUnionId("union_id_456");
when(douyinClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByDouyinOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByDouyinUnionId("union_id_456")).thenReturn(Mono.just(user));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("douyin") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithExistingUserByBinding() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
UserBinding binding = new UserBinding();
binding.setUserId(1L);
binding.setPlatform("douyin");
binding.setPlatformUnionId("union_id_456");
when(douyinClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByDouyinOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByDouyinUnionId("union_id_456")).thenReturn(Mono.empty());
when(userBindingRepository.findByPlatformAndUnionId("douyin", "union_id_456")).thenReturn(Mono.just(binding));
when(clientUserRepository.findById(1L)).thenReturn(Mono.just(user));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("douyin") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithNewUser() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser newUser = new ClientUser();
newUser.setId(1L);
newUser.setDouyinOpenId("open_id_123");
newUser.setDouyinUnionId("union_id_456");
newUser.setPhoneVerified(false);
UserBinding binding = new UserBinding();
binding.setId(1L);
binding.setUserId(1L);
binding.setPlatform("douyin");
binding.setPlatformOpenId("open_id_123");
binding.setPlatformUnionId("union_id_456");
when(douyinClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByDouyinOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByDouyinUnionId("union_id_456")).thenReturn(Mono.empty());
when(userBindingRepository.findByPlatformAndUnionId("douyin", "union_id_456")).thenReturn(Mono.empty());
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(newUser));
when(userBindingRepository.save(any(UserBinding.class))).thenReturn(Mono.just(binding));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getPlatform().equals("douyin") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository).save(any(ClientUser.class));
verify(userBindingRepository).save(any(UserBinding.class));
}
@Test
void testLoginWithNewUserWithoutUnionId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("valid_code");
request.setData(douyinRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setSessionKey("session_key");
ClientUser newUser = new ClientUser();
newUser.setId(1L);
newUser.setDouyinOpenId("open_id_123");
newUser.setPhoneVerified(false);
UserBinding binding = new UserBinding();
binding.setId(1L);
binding.setUserId(1L);
binding.setPlatform("douyin");
binding.setPlatformOpenId("open_id_123");
when(douyinClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByDouyinOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(newUser));
when(userBindingRepository.save(any(UserBinding.class))).thenReturn(Mono.just(binding));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getPlatform().equals("douyin") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).findByDouyinUnionId(anyString());
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
}
@Test
void testLoginWithAuthFailure() {
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("invalid_code");
request.setData(douyinRequest);
when(douyinClient.auth("invalid_code")).thenReturn(Mono.error(new Exception("Auth failed")));
StepVerifier.create(douyinLoginStrategy.login(request))
.expectError(Exception.class)
.verify();
}
}
@@ -0,0 +1,83 @@
package io.destiny.client.core.strategy;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class LoginStrategyFactoryTest {
@Mock
private WechatLoginStrategy wechatLoginStrategy;
@Mock
private DouyinLoginStrategy douyinLoginStrategy;
@Mock
private SmsLoginStrategy smsLoginStrategy;
private LoginStrategyFactory factory;
@BeforeEach
void setUp() {
when(wechatLoginStrategy.getLoginType()).thenReturn("wechat");
when(douyinLoginStrategy.getLoginType()).thenReturn("douyin");
when(smsLoginStrategy.getLoginType()).thenReturn("sms");
factory = new LoginStrategyFactory(List.of(wechatLoginStrategy, douyinLoginStrategy, smsLoginStrategy));
factory.init();
}
@Test
void testGetStrategy_Wechat() {
LoginStrategy strategy = factory.getStrategy("wechat");
assertNotNull(strategy);
assertEquals(wechatLoginStrategy, strategy);
}
@Test
void testGetStrategy_Douyin() {
LoginStrategy strategy = factory.getStrategy("douyin");
assertNotNull(strategy);
assertEquals(douyinLoginStrategy, strategy);
}
@Test
void testGetStrategy_Sms() {
LoginStrategy strategy = factory.getStrategy("sms");
assertNotNull(strategy);
assertEquals(smsLoginStrategy, strategy);
}
@Test
void testGetStrategy_InvalidType() {
assertThrows(ApplicationException.class, () -> {
factory.getStrategy("invalid");
});
}
@Test
void testGetStrategy_NullType() {
assertThrows(ApplicationException.class, () -> {
factory.getStrategy(null);
});
}
@Test
void testGetStrategy_EmptyType() {
assertThrows(ApplicationException.class, () -> {
factory.getStrategy("");
});
}
}
@@ -0,0 +1,275 @@
package io.destiny.client.core.strategy;
import io.destiny.client.core.exception.ClientUserAuthExceptionCode;
import io.destiny.client.dto.DouyinLoginRequest;
import io.destiny.client.dto.LoginRequest;
import io.destiny.client.dto.LoginResult;
import io.destiny.client.dto.SmsLoginRequest;
import io.destiny.client.dto.WechatLoginRequest;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class LoginStrategyProxyTest {
@Mock
private LoginStrategyFactory strategyFactory;
@Mock
private LoginStrategy loginStrategy;
@InjectMocks
private LoginStrategyProxy loginStrategyProxy;
@BeforeEach
void setUp() {
when(strategyFactory.getStrategy(any())).thenReturn(loginStrategy);
}
@Test
void testLoginSuccess() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("wechat");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
verify(loginStrategy).login(request);
}
@Test
void testLoginWithNullIpAddress() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress(null);
request.setData(new WechatLoginRequest());
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("wechat");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginFailureWithApplicationException() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
ApplicationException exception = new ApplicationException(ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD);
when(loginStrategy.login(any())).thenReturn(Mono.error(exception));
StepVerifier.create(loginStrategyProxy.login(request))
.expectError(ApplicationException.class)
.verify();
}
@Test
void testLoginFailureWithNonApplicationException() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
RuntimeException exception = new RuntimeException("Unexpected error");
when(loginStrategy.login(any())).thenReturn(Mono.error(exception));
StepVerifier.create(loginStrategyProxy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_LOGIN_FAILED))
.verify();
}
@Test
void testAccountLockAfterMultipleFailedAttempts() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
ApplicationException exception = new ApplicationException(ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD);
when(loginStrategy.login(any())).thenReturn(Mono.error(exception));
for (int i = 0; i < 5; i++) {
StepVerifier.create(loginStrategyProxy.login(request))
.expectError(ApplicationException.class)
.verify();
}
StepVerifier.create(loginStrategyProxy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode().equals(ClientUserAuthExceptionCode.CLIENT_ACCOUNT_LOCKED))
.verify();
}
@Test
void testLoginWithDouyinRequest() {
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode("douyin_code");
request.setData(douyinRequest);
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("douyin");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginWithDouyinRequestNullCode() {
LoginRequest request = new LoginRequest();
request.setLoginType("douyin");
request.setIpAddress("192.168.1.1");
DouyinLoginRequest douyinRequest = new DouyinLoginRequest();
douyinRequest.setCode(null);
request.setData(douyinRequest);
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("douyin");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginWithSmsRequest() {
LoginRequest request = new LoginRequest();
request.setLoginType("sms");
request.setIpAddress("192.168.1.1");
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone("13800138000");
smsRequest.setCode("123456");
request.setData(smsRequest);
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("sms");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginWithSmsRequestNullPhone() {
LoginRequest request = new LoginRequest();
request.setLoginType("sms");
request.setIpAddress("192.168.1.1");
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(null);
smsRequest.setCode("123456");
request.setData(smsRequest);
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("sms");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginWithNullLoginType() {
LoginRequest request = new LoginRequest();
request.setLoginType(null);
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("wechat");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testLoginWithNullData() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
request.setData(null);
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("password");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
@Test
void testClearAttemptRecordAfterSuccessfulLogin() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
request.setData(new WechatLoginRequest());
ApplicationException exception = new ApplicationException(ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD);
when(loginStrategy.login(any())).thenReturn(Mono.error(exception));
StepVerifier.create(loginStrategyProxy.login(request))
.expectError(ApplicationException.class)
.verify();
LoginResult result = new LoginResult();
result.setUserId(1L);
result.setPlatform("wechat");
when(loginStrategy.login(any())).thenReturn(Mono.just(result));
StepVerifier.create(loginStrategyProxy.login(request))
.expectNext(result)
.verifyComplete();
}
}
@@ -0,0 +1,385 @@
package io.destiny.client.core.strategy;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.domain.SmsVerificationCode;
import io.destiny.client.core.enums.SmsCodeType;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.client.core.repository.ISmsVerificationCodeRepository;
import io.destiny.client.core.service.ClientUserAuthService;
import io.destiny.client.dto.LoginRequest;
import io.destiny.client.dto.LoginResult;
import io.destiny.client.dto.SmsLoginRequest;
import io.destiny.client.security.JwtTokenProvider;
import io.destiny.common.exception.ApplicationException;
import io.destiny.common.primitive.PhoneNumber;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.LocalDateTime;
import static io.destiny.client.core.exception.ClientUserAuthExceptionCode.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class SmsLoginStrategyTest {
@Mock
private ClientUserAuthService clientUserAuthService;
@Mock
private JwtTokenProvider jwtTokenProvider;
@Mock
private IClientUserRepository clientUserRepository;
@Mock
private ISmsVerificationCodeRepository smsVerificationCodeRepository;
private SmsLoginStrategy strategy;
private static final String TEST_PHONE = "13800138000";
private static final String TEST_CODE = "123456";
private static final Long TEST_USER_ID = 12345L;
private static final String TEST_TOKEN = "test_jwt_token";
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
strategy = new SmsLoginStrategy(clientUserAuthService, jwtTokenProvider, clientUserRepository, smsVerificationCodeRepository);
}
@Test
void testGetLoginType() {
String result = strategy.getLoginType();
assert "sms".equals(result);
}
@Test
void testValidateRequest_Success() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectNext(request)
.verifyComplete();
}
@Test
void testValidateRequest_NullPhone() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(null);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
}
@Test
void testValidateRequest_EmptyPhone() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone("");
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
}
@Test
void testValidateRequest_NullCode() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(null);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
}
@Test
void testValidateRequest_EmptyCode() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode("");
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
}
@Test
void testValidateRequest_InvalidDataType() {
LoginRequest request = new LoginRequest();
request.setData(new Object());
Mono<LoginRequest> result = strategy.validateRequest(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
}
@Test
void testLogin_ExistingUser_Success() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
verificationCode.setVerified(false);
verificationCode.setVerifyCount(0);
ClientUser existingUser = new ClientUser();
existingUser.setId(TEST_USER_ID);
existingUser.setPhone(PhoneNumber.of(TEST_PHONE));
existingUser.setUsername(TEST_PHONE);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
when(smsVerificationCodeRepository.markAsVerified(any())).thenReturn(Mono.empty());
when(clientUserRepository.findByPhone(PhoneNumber.of(TEST_PHONE))).thenReturn(Mono.just(existingUser));
when(jwtTokenProvider.generateToken(TEST_USER_ID, "sms")).thenReturn(TEST_TOKEN);
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectNextMatches(loginResult ->
TEST_USER_ID.equals(loginResult.getUserId()) &&
TEST_PHONE.equals(loginResult.getUsername()) &&
TEST_PHONE.equals(loginResult.getPhone()) &&
"sms".equals(loginResult.getPlatform()) &&
TEST_TOKEN.equals(loginResult.getToken()))
.verifyComplete();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(smsVerificationCodeRepository, times(1)).markAsVerified(any());
verify(clientUserRepository, times(1)).findByPhone(PhoneNumber.of(TEST_PHONE));
verify(jwtTokenProvider, times(1)).generateToken(TEST_USER_ID, "sms");
}
@Test
void testLogin_NewUser_Success() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
verificationCode.setVerified(false);
verificationCode.setVerifyCount(0);
ClientUser newUser = new ClientUser();
newUser.setId(TEST_USER_ID);
newUser.setPhone(PhoneNumber.of(TEST_PHONE));
newUser.setPhoneVerified(true);
newUser.setUsername(TEST_PHONE);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
when(smsVerificationCodeRepository.markAsVerified(any())).thenReturn(Mono.empty());
when(clientUserRepository.findByPhone(PhoneNumber.of(TEST_PHONE))).thenReturn(Mono.empty());
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(newUser));
when(jwtTokenProvider.generateToken(TEST_USER_ID, "sms")).thenReturn(TEST_TOKEN);
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectNextMatches(loginResult ->
TEST_USER_ID.equals(loginResult.getUserId()) &&
TEST_PHONE.equals(loginResult.getUsername()) &&
TEST_PHONE.equals(loginResult.getPhone()) &&
"sms".equals(loginResult.getPlatform()) &&
TEST_TOKEN.equals(loginResult.getToken()))
.verifyComplete();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(smsVerificationCodeRepository, times(1)).markAsVerified(any());
verify(clientUserRepository, times(1)).findByPhone(PhoneNumber.of(TEST_PHONE));
verify(clientUserRepository, times(1)).save(any(ClientUser.class));
verify(jwtTokenProvider, times(1)).generateToken(TEST_USER_ID, "sms");
}
@Test
void testLogin_CodeNotFound() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.empty());
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(clientUserRepository, never()).findByPhone(any());
verify(jwtTokenProvider, never()).generateToken(any(), anyString());
}
@Test
void testLogin_CodeExpired() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().minusMinutes(1));
verificationCode.setVerified(false);
verificationCode.setVerifyCount(0);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_EXPIRED))
.verify();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(clientUserRepository, never()).findByPhone(any());
verify(jwtTokenProvider, never()).generateToken(any(), anyString());
}
@Test
void testLogin_CodeAlreadyUsed() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
verificationCode.setVerified(true);
verificationCode.setVerifyCount(0);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_USED))
.verify();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(clientUserRepository, never()).findByPhone(any());
verify(jwtTokenProvider, never()).generateToken(any(), anyString());
}
@Test
void testLogin_VerifyCountExceeded() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode(TEST_CODE);
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
verificationCode.setVerified(false);
verificationCode.setVerifyCount(5);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_EXCEEDED))
.verify();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(clientUserRepository, never()).findByPhone(any());
verify(jwtTokenProvider, never()).generateToken(any(), anyString());
}
@Test
void testLogin_WrongCode() {
SmsLoginRequest smsRequest = new SmsLoginRequest();
smsRequest.setPhone(TEST_PHONE);
smsRequest.setCode("999999");
LoginRequest request = new LoginRequest();
request.setData(smsRequest);
SmsVerificationCode verificationCode = new SmsVerificationCode();
verificationCode.setCode(TEST_CODE);
verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
verificationCode.setVerified(false);
verificationCode.setVerifyCount(0);
when(smsVerificationCodeRepository.findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode()))
.thenReturn(Mono.just(verificationCode));
when(smsVerificationCodeRepository.save(any(SmsVerificationCode.class))).thenReturn(Mono.just(verificationCode));
Mono<LoginResult> result = strategy.login(request);
StepVerifier.create(result)
.expectErrorMatches(ex -> ex instanceof ApplicationException &&
((ApplicationException) ex).getExceptionCode().equals(CLIENT_SMS_CODE_INVALID))
.verify();
verify(smsVerificationCodeRepository, times(1)).findLatestByPhoneAndType(TEST_PHONE, SmsCodeType.LOGIN.getCode());
verify(smsVerificationCodeRepository, times(1)).save(any(SmsVerificationCode.class));
verify(clientUserRepository, never()).findByPhone(any());
verify(jwtTokenProvider, never()).generateToken(any(), anyString());
}
}
@@ -0,0 +1,273 @@
package io.destiny.client.core.strategy;
import io.destiny.client.core.domain.ClientLoginLog;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.repository.IClientLoginLogRepository;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.client.core.service.ClientUserAuthService;
import io.destiny.client.dto.LoginRequest;
import io.destiny.client.security.JwtTokenProvider;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.password.PasswordEncoder;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.HashMap;
import java.util.Map;
import static io.destiny.client.core.exception.ClientUserAuthExceptionCode.CLIENT_INVALID_USERNAME_OR_PASSWORD;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UsernamePasswordLoginStrategyTest {
@Mock
private ClientUserAuthService clientUserAuthService;
@Mock
private JwtTokenProvider jwtTokenProvider;
@Mock
private IClientUserRepository clientUserRepository;
@Mock
private IClientLoginLogRepository clientLoginLogRepository;
@Mock
private PasswordEncoder passwordEncoder;
@InjectMocks
private UsernamePasswordLoginStrategy usernamePasswordLoginStrategy;
@Test
void testGetLoginType() {
assertEquals("password", usernamePasswordLoginStrategy.getLoginType());
}
@Test
void testLoginSuccess() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "testuser");
data.put("password", "password123");
request.setData(data);
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setPassword("encoded_password");
when(clientUserRepository.findByUsername("testuser")).thenReturn(Mono.just(user));
when(passwordEncoder.matches("password123", "encoded_password")).thenReturn(true);
when(clientLoginLogRepository.save(any(ClientLoginLog.class)))
.thenReturn(Mono.just(new ClientLoginLog()));
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("password") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository).findByUsername("testuser");
verify(passwordEncoder).matches("password123", "encoded_password");
verify(clientLoginLogRepository).save(any(ClientLoginLog.class));
}
@Test
void testLoginWithNullUsername() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", null);
data.put("password", "password123");
request.setData(data);
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository, never()).findByUsername(anyString());
}
@Test
void testLoginWithEmptyUsername() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "");
data.put("password", "password123");
request.setData(data);
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository, never()).findByUsername(anyString());
}
@Test
void testLoginWithNullPassword() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "testuser");
data.put("password", null);
request.setData(data);
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository, never()).findByUsername(anyString());
}
@Test
void testLoginWithEmptyPassword() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "testuser");
data.put("password", "");
request.setData(data);
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository, never()).findByUsername(anyString());
}
@Test
void testLoginWithInvalidData() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
request.setData("invalid_data");
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository, never()).findByUsername(anyString());
}
@Test
void testLoginWithUserNotFound() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "nonexistent");
data.put("password", "password123");
request.setData(data);
when(clientUserRepository.findByUsername("nonexistent")).thenReturn(Mono.empty());
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository).findByUsername("nonexistent");
verify(passwordEncoder, never()).matches(anyString(), anyString());
}
@Test
void testLoginWithWrongPassword() {
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress("192.168.1.1");
Map<String, Object> data = new HashMap<>();
data.put("username", "testuser");
data.put("password", "wrong_password");
request.setData(data);
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setPassword("encoded_password");
when(clientUserRepository.findByUsername("testuser")).thenReturn(Mono.just(user));
when(passwordEncoder.matches("wrong_password", "encoded_password")).thenReturn(false);
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_USERNAME_OR_PASSWORD))
.verify();
verify(clientUserRepository).findByUsername("testuser");
verify(passwordEncoder).matches("wrong_password", "encoded_password");
verify(clientLoginLogRepository, never()).save(any(ClientLoginLog.class));
}
@Test
void testLoginWithNullIpAddress() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("password");
request.setIpAddress(null);
Map<String, Object> data = new HashMap<>();
data.put("username", "testuser");
data.put("password", "password123");
request.setData(data);
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setPassword("encoded_password");
when(clientUserRepository.findByUsername("testuser")).thenReturn(Mono.just(user));
when(passwordEncoder.matches("password123", "encoded_password")).thenReturn(true);
when(clientLoginLogRepository.save(any(ClientLoginLog.class)))
.thenReturn(Mono.just(new ClientLoginLog()));
StepVerifier.create(usernamePasswordLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("password"))
.verifyComplete();
verify(clientUserRepository).findByUsername("testuser");
verify(passwordEncoder).matches("password123", "encoded_password");
verify(clientLoginLogRepository).save(any(ClientLoginLog.class));
}
}
@@ -0,0 +1,328 @@
package io.destiny.client.core.strategy;
import io.destiny.client.client.WechatMiniProgramClient;
import io.destiny.client.core.domain.ClientUser;
import io.destiny.client.core.domain.UserBinding;
import io.destiny.client.core.repository.IClientUserRepository;
import io.destiny.client.core.repository.IUserBindingRepository;
import io.destiny.client.core.service.ClientUserAuthService;
import io.destiny.client.dto.LoginRequest;
import io.destiny.client.dto.WechatAuthResponse;
import io.destiny.client.dto.WechatLoginRequest;
import io.destiny.client.security.JwtTokenProvider;
import io.destiny.common.exception.ApplicationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import static io.destiny.client.core.exception.ClientUserAuthExceptionCode.CLIENT_INVALID_WECHAT_CODE;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class WechatLoginStrategyTest {
@Mock
private ClientUserAuthService clientUserAuthService;
@Mock
private JwtTokenProvider jwtTokenProvider;
@Mock
private WechatMiniProgramClient wechatClient;
@Mock
private IClientUserRepository clientUserRepository;
@Mock
private IUserBindingRepository userBindingRepository;
@InjectMocks
private WechatLoginStrategy wechatLoginStrategy;
@BeforeEach
void setUp() {
}
@Test
void testGetLoginType() {
assertEquals("wechat", wechatLoginStrategy.getLoginType());
}
@Test
void testValidateRequestWithValidData() {
LoginRequest request = new LoginRequest();
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
StepVerifier.create(wechatLoginStrategy.validateRequest(request))
.expectNext(request)
.verifyComplete();
}
@Test
void testValidateRequestWithNullCode() {
LoginRequest request = new LoginRequest();
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode(null);
request.setData(wechatRequest);
StepVerifier.create(wechatLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_WECHAT_CODE))
.verify();
}
@Test
void testValidateRequestWithEmptyCode() {
LoginRequest request = new LoginRequest();
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("");
request.setData(wechatRequest);
StepVerifier.create(wechatLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_WECHAT_CODE))
.verify();
}
@Test
void testValidateRequestWithInvalidDataType() {
LoginRequest request = new LoginRequest();
request.setData("invalid_data");
StepVerifier.create(wechatLoginStrategy.validateRequest(request))
.expectErrorMatches(error -> error instanceof ApplicationException &&
((ApplicationException) error).getExceptionCode()
.equals(CLIENT_INVALID_WECHAT_CODE))
.verify();
}
@Test
void testLoginSuccessWithExistingUserByOpenId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setWechatOpenId("open_id_123");
when(wechatClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByWechatOpenId("open_id_123")).thenReturn(Mono.just(user));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("wechat") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).findByWechatUnionId(anyString());
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithExistingUserByUnionId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
user.setWechatUnionId("union_id_456");
when(wechatClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByWechatOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByWechatUnionId("union_id_456")).thenReturn(Mono.just(user));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("wechat") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithExistingUserByBinding() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser user = new ClientUser();
user.setId(1L);
user.setUsername("testuser");
UserBinding binding = new UserBinding();
binding.setUserId(1L);
binding.setPlatform("wechat");
binding.setPlatformUnionId("union_id_456");
when(wechatClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByWechatOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByWechatUnionId("union_id_456")).thenReturn(Mono.empty());
when(userBindingRepository.findByPlatformAndUnionId("wechat", "union_id_456"))
.thenReturn(Mono.just(binding));
when(clientUserRepository.findById(1L)).thenReturn(Mono.just(user));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getUsername().equals("testuser") &&
result.getPlatform().equals("wechat") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).save(any(ClientUser.class));
}
@Test
void testLoginSuccessWithNewUser() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setUnionId("union_id_456");
authResponse.setSessionKey("session_key");
ClientUser newUser = new ClientUser();
newUser.setId(1L);
newUser.setWechatOpenId("open_id_123");
newUser.setWechatUnionId("union_id_456");
newUser.setPhoneVerified(false);
UserBinding binding = new UserBinding();
binding.setId(1L);
binding.setUserId(1L);
binding.setPlatform("wechat");
binding.setPlatformOpenId("open_id_123");
binding.setPlatformUnionId("union_id_456");
when(wechatClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByWechatOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.findByWechatUnionId("union_id_456")).thenReturn(Mono.empty());
when(userBindingRepository.findByPlatformAndUnionId("wechat", "union_id_456")).thenReturn(Mono.empty());
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(newUser));
when(userBindingRepository.save(any(UserBinding.class))).thenReturn(Mono.just(binding));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getPlatform().equals("wechat") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository).save(any(ClientUser.class));
verify(userBindingRepository).save(any(UserBinding.class));
}
@Test
void testLoginWithNewUserWithoutUnionId() {
when(jwtTokenProvider.generateToken(anyLong(), anyString())).thenReturn("test-token");
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("valid_code");
request.setData(wechatRequest);
WechatAuthResponse authResponse = new WechatAuthResponse();
authResponse.setOpenId("open_id_123");
authResponse.setSessionKey("session_key");
ClientUser newUser = new ClientUser();
newUser.setId(1L);
newUser.setWechatOpenId("open_id_123");
newUser.setPhoneVerified(false);
UserBinding binding = new UserBinding();
binding.setId(1L);
binding.setUserId(1L);
binding.setPlatform("wechat");
binding.setPlatformOpenId("open_id_123");
when(wechatClient.auth("valid_code")).thenReturn(Mono.just(authResponse));
when(clientUserRepository.findByWechatOpenId("open_id_123")).thenReturn(Mono.empty());
when(clientUserRepository.save(any(ClientUser.class))).thenReturn(Mono.just(newUser));
when(userBindingRepository.save(any(UserBinding.class))).thenReturn(Mono.just(binding));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectNextMatches(result -> result.getUserId().equals(1L) &&
result.getPlatform().equals("wechat") &&
result.getToken().equals("test-token"))
.verifyComplete();
verify(clientUserRepository, never()).findByWechatUnionId(anyString());
verify(userBindingRepository, never()).findByPlatformAndUnionId(anyString(), anyString());
}
@Test
void testLoginWithAuthFailure() {
LoginRequest request = new LoginRequest();
request.setLoginType("wechat");
request.setIpAddress("192.168.1.1");
WechatLoginRequest wechatRequest = new WechatLoginRequest();
wechatRequest.setCode("invalid_code");
request.setData(wechatRequest);
when(wechatClient.auth("invalid_code")).thenReturn(Mono.error(new Exception("Auth failed")));
StepVerifier.create(wechatLoginStrategy.login(request))
.expectError(Exception.class)
.verify();
}
}
@@ -0,0 +1,49 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AccountBindRequestTest {
@Test
void testGettersAndSetters() {
AccountBindRequest request = new AccountBindRequest();
request.setPlatform("wechat");
request.setCode("test_code_123");
assertEquals("wechat", request.getPlatform());
assertEquals("test_code_123", request.getCode());
}
@Test
void testDefaultValues() {
AccountBindRequest request = new AccountBindRequest();
assertNull(request.getPlatform());
assertNull(request.getCode());
}
@Test
void testSetNullValues() {
AccountBindRequest request = new AccountBindRequest();
request.setPlatform(null);
request.setCode(null);
assertNull(request.getPlatform());
assertNull(request.getCode());
}
@Test
void testSetEmptyValues() {
AccountBindRequest request = new AccountBindRequest();
request.setPlatform("");
request.setCode("");
assertEquals("", request.getPlatform());
assertEquals("", request.getCode());
}
}
@@ -0,0 +1,86 @@
package io.destiny.client.dto;
import io.destiny.client.core.domain.query.ClientUserLogin;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ClientUserLoginRequestTest {
@Test
void testGettersAndSetters() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
request.setUsername("testuser");
request.setPassword("password123");
request.setIpAddress("192.168.1.1");
assertEquals("testuser", request.getUsername());
assertEquals("password123", request.getPassword());
assertEquals("192.168.1.1", request.getIpAddress());
}
@Test
void testDefaultValues() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getIpAddress());
}
@Test
void testSetNullValues() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
request.setUsername(null);
request.setPassword(null);
request.setIpAddress(null);
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getIpAddress());
}
@Test
void testSetEmptyValues() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
request.setUsername("");
request.setPassword("");
request.setIpAddress("");
assertEquals("", request.getUsername());
assertEquals("", request.getPassword());
assertEquals("", request.getIpAddress());
}
@Test
void testToDomain() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
request.setUsername("testuser");
request.setPassword("password123");
request.setIpAddress("192.168.1.1");
ClientUserLogin domain = request.toDomain();
assertNotNull(domain);
assertEquals("testuser", domain.getUsername());
assertEquals("password123", domain.getPassword());
assertNotNull(domain.getIpAddress());
assertEquals("192.168.1.1", domain.getIpAddress().getValue());
}
@Test
void testToDomainWithNullValues() {
ClientUserLoginRequest request = new ClientUserLoginRequest();
ClientUserLogin domain = request.toDomain();
assertNotNull(domain);
assertNull(domain.getUsername());
assertNull(domain.getPassword());
assertNull(domain.getIpAddress());
}
}
@@ -0,0 +1,123 @@
package io.destiny.client.dto;
import io.destiny.client.core.domain.ClientUser;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ClientUserRegisterRequestTest {
@Test
void testGettersAndSetters() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
request.setUsername("testuser");
request.setPassword("password123");
request.setEmail("test@example.com");
request.setPhone("13800138000");
request.setGender("male");
assertEquals("testuser", request.getUsername());
assertEquals("password123", request.getPassword());
assertEquals("test@example.com", request.getEmail());
assertEquals("13800138000", request.getPhone());
assertEquals("male", request.getGender());
}
@Test
void testDefaultValues() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getEmail());
assertNull(request.getPhone());
assertNull(request.getGender());
}
@Test
void testSetNullValues() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
request.setUsername(null);
request.setPassword(null);
request.setEmail(null);
request.setPhone(null);
request.setGender(null);
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getEmail());
assertNull(request.getPhone());
assertNull(request.getGender());
}
@Test
void testSetEmptyValues() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
request.setUsername("");
request.setPassword("");
request.setEmail("");
request.setPhone("");
request.setGender("");
assertEquals("", request.getUsername());
assertEquals("", request.getPassword());
assertEquals("", request.getEmail());
assertEquals("", request.getPhone());
assertEquals("", request.getGender());
}
@Test
void testToDomain() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
request.setUsername("testuser");
request.setPassword("password123");
request.setEmail("test@example.com");
request.setPhone("13800138000");
request.setGender("male");
ClientUser domain = request.toDomain();
assertNotNull(domain);
assertEquals("testuser", domain.getUsername());
assertEquals("password123", domain.getPassword());
assertNotNull(domain.getEmail());
assertEquals("test@example.com", domain.getEmail().getValue());
assertNotNull(domain.getPhone());
assertEquals("13800138000", domain.getPhone().getValue());
assertEquals("male", domain.getGender());
}
@Test
void testToDomainWithNullValues() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
ClientUser domain = request.toDomain();
assertNotNull(domain);
assertNull(domain.getUsername());
assertNull(domain.getPassword());
assertNull(domain.getEmail());
assertNull(domain.getPhone());
assertNull(domain.getGender());
}
@Test
void testToDomainWithPartialValues() {
ClientUserRegisterRequest request = new ClientUserRegisterRequest();
request.setUsername("testuser");
request.setPassword("password123");
ClientUser domain = request.toDomain();
assertNotNull(domain);
assertEquals("testuser", domain.getUsername());
assertEquals("password123", domain.getPassword());
assertNull(domain.getEmail());
assertNull(domain.getPhone());
assertNull(domain.getGender());
}
}
@@ -0,0 +1,56 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class DouyinLoginRequestTest {
@Test
void testGettersAndSetters() {
DouyinLoginRequest request = new DouyinLoginRequest();
request.setCode("test_code_123");
request.setPlatform("douyin");
request.setIpAddress("192.168.1.1");
assertEquals("test_code_123", request.getCode());
assertEquals("douyin", request.getPlatform());
assertEquals("192.168.1.1", request.getIpAddress());
}
@Test
void testDefaultValues() {
DouyinLoginRequest request = new DouyinLoginRequest();
assertNull(request.getCode());
assertNull(request.getPlatform());
assertNull(request.getIpAddress());
}
@Test
void testSetNullValues() {
DouyinLoginRequest request = new DouyinLoginRequest();
request.setCode(null);
request.setPlatform(null);
request.setIpAddress(null);
assertNull(request.getCode());
assertNull(request.getPlatform());
assertNull(request.getIpAddress());
}
@Test
void testSetEmptyValues() {
DouyinLoginRequest request = new DouyinLoginRequest();
request.setCode("");
request.setPlatform("");
request.setIpAddress("");
assertEquals("", request.getCode());
assertEquals("", request.getPlatform());
assertEquals("", request.getIpAddress());
}
}
@@ -0,0 +1,72 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class LoginRequestTest {
@Test
void testGettersAndSetters() {
LoginRequest request = new LoginRequest();
request.setLoginType("sms");
request.setIpAddress("192.168.1.1");
request.setData(new SmsLoginRequest());
assertEquals("sms", request.getLoginType());
assertEquals("192.168.1.1", request.getIpAddress());
assertNotNull(request.getData());
assertTrue(request.getData() instanceof SmsLoginRequest);
}
@Test
void testDefaultValues() {
LoginRequest request = new LoginRequest();
assertNull(request.getLoginType());
assertNull(request.getIpAddress());
assertNull(request.getData());
}
@Test
void testSetNullValues() {
LoginRequest request = new LoginRequest();
request.setLoginType(null);
request.setIpAddress(null);
request.setData(null);
assertNull(request.getLoginType());
assertNull(request.getIpAddress());
assertNull(request.getData());
}
@Test
void testSetEmptyValues() {
LoginRequest request = new LoginRequest();
request.setLoginType("");
request.setIpAddress("");
assertEquals("", request.getLoginType());
assertEquals("", request.getIpAddress());
}
@Test
void testSetDifferentDataTypes() {
LoginRequest request = new LoginRequest();
SmsLoginRequest smsRequest = new SmsLoginRequest();
request.setData(smsRequest);
assertEquals(smsRequest, request.getData());
PasswordLoginRequest passwordRequest = new PasswordLoginRequest();
request.setData(passwordRequest);
assertEquals(passwordRequest, request.getData());
WechatLoginRequest wechatRequest = new WechatLoginRequest();
request.setData(wechatRequest);
assertEquals(wechatRequest, request.getData());
}
}
@@ -0,0 +1,56 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PasswordLoginRequestTest {
@Test
void testGettersAndSetters() {
PasswordLoginRequest request = new PasswordLoginRequest();
request.setUsername("testuser");
request.setPassword("password123");
request.setIpAddress("192.168.1.1");
assertEquals("testuser", request.getUsername());
assertEquals("password123", request.getPassword());
assertEquals("192.168.1.1", request.getIpAddress());
}
@Test
void testDefaultValues() {
PasswordLoginRequest request = new PasswordLoginRequest();
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getIpAddress());
}
@Test
void testSetNullValues() {
PasswordLoginRequest request = new PasswordLoginRequest();
request.setUsername(null);
request.setPassword(null);
request.setIpAddress(null);
assertNull(request.getUsername());
assertNull(request.getPassword());
assertNull(request.getIpAddress());
}
@Test
void testSetEmptyValues() {
PasswordLoginRequest request = new PasswordLoginRequest();
request.setUsername("");
request.setPassword("");
request.setIpAddress("");
assertEquals("", request.getUsername());
assertEquals("", request.getPassword());
assertEquals("", request.getIpAddress());
}
}
@@ -0,0 +1,49 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SmsCodeSendRequestTest {
@Test
void testGettersAndSetters() {
SmsCodeSendRequest request = new SmsCodeSendRequest();
request.setPhone("13800138000");
request.setType("login");
assertEquals("13800138000", request.getPhone());
assertEquals("login", request.getType());
}
@Test
void testDefaultValues() {
SmsCodeSendRequest request = new SmsCodeSendRequest();
assertNull(request.getPhone());
assertNull(request.getType());
}
@Test
void testSetNullValues() {
SmsCodeSendRequest request = new SmsCodeSendRequest();
request.setPhone(null);
request.setType(null);
assertNull(request.getPhone());
assertNull(request.getType());
}
@Test
void testSetEmptyValues() {
SmsCodeSendRequest request = new SmsCodeSendRequest();
request.setPhone("");
request.setType("");
assertEquals("", request.getPhone());
assertEquals("", request.getType());
}
}
@@ -0,0 +1,56 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SmsLoginRequestTest {
@Test
void testGettersAndSetters() {
SmsLoginRequest request = new SmsLoginRequest();
request.setPhone("13800138000");
request.setCode("123456");
request.setIpAddress("192.168.1.1");
assertEquals("13800138000", request.getPhone());
assertEquals("123456", request.getCode());
assertEquals("192.168.1.1", request.getIpAddress());
}
@Test
void testDefaultValues() {
SmsLoginRequest request = new SmsLoginRequest();
assertNull(request.getPhone());
assertNull(request.getCode());
assertNull(request.getIpAddress());
}
@Test
void testSetNullValues() {
SmsLoginRequest request = new SmsLoginRequest();
request.setPhone(null);
request.setCode(null);
request.setIpAddress(null);
assertNull(request.getPhone());
assertNull(request.getCode());
assertNull(request.getIpAddress());
}
@Test
void testSetEmptyValues() {
SmsLoginRequest request = new SmsLoginRequest();
request.setPhone("");
request.setCode("");
request.setIpAddress("");
assertEquals("", request.getPhone());
assertEquals("", request.getCode());
assertEquals("", request.getIpAddress());
}
}
@@ -0,0 +1,56 @@
package io.destiny.client.dto;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class WechatLoginRequestTest {
@Test
void testGettersAndSetters() {
WechatLoginRequest request = new WechatLoginRequest();
request.setCode("test_code_123");
request.setPlatform("wechat");
request.setIpAddress("192.168.1.1");
assertEquals("test_code_123", request.getCode());
assertEquals("wechat", request.getPlatform());
assertEquals("192.168.1.1", request.getIpAddress());
}
@Test
void testDefaultValues() {
WechatLoginRequest request = new WechatLoginRequest();
assertNull(request.getCode());
assertNull(request.getPlatform());
assertNull(request.getIpAddress());
}
@Test
void testSetNullValues() {
WechatLoginRequest request = new WechatLoginRequest();
request.setCode(null);
request.setPlatform(null);
request.setIpAddress(null);
assertNull(request.getCode());
assertNull(request.getPlatform());
assertNull(request.getIpAddress());
}
@Test
void testSetEmptyValues() {
WechatLoginRequest request = new WechatLoginRequest();
request.setCode("");
request.setPlatform("");
request.setIpAddress("");
assertEquals("", request.getCode());
assertEquals("", request.getPlatform());
assertEquals("", request.getIpAddress());
}
}
@@ -0,0 +1,125 @@
package io.destiny.client.security;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
class JwtTokenProviderTest {
@InjectMocks
private JwtTokenProvider jwtTokenProvider;
private static final String SECRET_KEY = "your-secret-key-must-be-at-least-256-bits-long-for-hs256-algorithm";
private static final Long EXPIRATION = 86400000L;
private static final Long USER_ID = 123L;
private static final String USERNAME = "testuser";
@BeforeEach
void setUp() {
ReflectionTestUtils.setField(jwtTokenProvider, "secret", SECRET_KEY);
ReflectionTestUtils.setField(jwtTokenProvider, "expiration", EXPIRATION);
}
@Test
void testGenerateToken_Success() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
assertNotNull(token);
assertFalse(token.isEmpty());
}
@Test
void testGetUserIdFromToken_Success() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
Long userId = jwtTokenProvider.getUserIdFromToken(token);
assertEquals(USER_ID, userId);
}
@Test
void testGetUserIdFromToken_InvalidToken() {
Long userId = jwtTokenProvider.getUserIdFromToken("invalid.token.here");
assertNull(userId);
}
@Test
void testGetUserIdFromToken_NullToken() {
Long userId = jwtTokenProvider.getUserIdFromToken(null);
assertNull(userId);
}
@Test
void testGetUsernameFromToken_Success() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
String username = jwtTokenProvider.getUsernameFromToken(token);
assertEquals(USERNAME, username);
}
@Test
void testGetUsernameFromToken_InvalidToken() {
String username = jwtTokenProvider.getUsernameFromToken("invalid.token.here");
assertNull(username);
}
@Test
void testGetUsernameFromToken_NullToken() {
String username = jwtTokenProvider.getUsernameFromToken(null);
assertNull(username);
}
@Test
void testValidateToken_Success() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
Boolean isValid = jwtTokenProvider.validateToken(token);
assertTrue(isValid);
}
@Test
void testValidateToken_InvalidToken() {
Boolean isValid = jwtTokenProvider.validateToken("invalid.token.here");
assertFalse(isValid);
}
@Test
void testValidateToken_NullToken() {
Boolean isValid = jwtTokenProvider.validateToken(null);
assertFalse(isValid);
}
@Test
void testIsTokenExpired_False() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
Boolean isExpired = jwtTokenProvider.isTokenExpired(token);
assertFalse(isExpired);
}
@Test
void testIsTokenExpired_InvalidToken() {
Boolean isExpired = jwtTokenProvider.isTokenExpired("invalid.token.here");
assertTrue(isExpired);
}
@Test
void testIsTokenExpired_NullToken() {
Boolean isExpired = jwtTokenProvider.isTokenExpired(null);
assertTrue(isExpired);
}
@Test
void testGenerateToken_DifferentUsers() {
String token1 = jwtTokenProvider.generateToken(1L, "user1");
String token2 = jwtTokenProvider.generateToken(2L, "user2");
assertNotEquals(token1, token2);
}
@Test
void testGetUserIdFromToken_CorrectUser() {
String token = jwtTokenProvider.generateToken(USER_ID, USERNAME);
Long userId = jwtTokenProvider.getUserIdFromToken(token);
assertEquals(USER_ID, userId);
}
}