|
|
@@ -1,312 +0,0 @@
|
|
|
-package com.moka.gdtauto.service;
|
|
|
-
|
|
|
-import com.moka.gdtauto.config.TencentAdsConfig;
|
|
|
-import com.moka.gdtauto.entity.TencentAdsAuth;
|
|
|
-import com.moka.gdtauto.mapper.TencentAdsAuthMapper;
|
|
|
-import com.tencent.ads.ApiContextConfig;
|
|
|
-import com.tencent.ads.container.v3.OauthApiContainer;
|
|
|
-import com.tencent.ads.exception.TencentAdsResponseException;
|
|
|
-import com.tencent.ads.exception.TencentAdsSDKException;
|
|
|
-import com.tencent.ads.model.v3.OauthTokenResponseData;
|
|
|
-import com.tencent.ads.v3.TencentAds;
|
|
|
-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.MockedStatic;
|
|
|
-import org.mockito.junit.jupiter.MockitoExtension;
|
|
|
-import org.mockito.junit.jupiter.MockitoSettings;
|
|
|
-import org.mockito.quality.Strictness;
|
|
|
-
|
|
|
-import java.time.LocalDateTime;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
-
|
|
|
-import static org.junit.jupiter.api.Assertions.*;
|
|
|
-import static org.mockito.ArgumentMatchers.*;
|
|
|
-import static org.mockito.Mockito.*;
|
|
|
-
|
|
|
-/**
|
|
|
- * TencentAdsAuthService单元测试
|
|
|
- *
|
|
|
- * @author moka
|
|
|
- * @since 2026-02-03
|
|
|
- */
|
|
|
-@ExtendWith(MockitoExtension.class)
|
|
|
-@MockitoSettings(strictness = Strictness.LENIENT)
|
|
|
-class TencentAdsAuthServiceTest {
|
|
|
-
|
|
|
- @Mock
|
|
|
- private TencentAdsAuthMapper authMapper;
|
|
|
-
|
|
|
- @Mock
|
|
|
- private TencentAdsConfig tencentAdsConfig;
|
|
|
-
|
|
|
- @InjectMocks
|
|
|
- private TencentAdsAuthService authService;
|
|
|
-
|
|
|
- private static final String TEST_APP_ID = "1234567890";
|
|
|
- private static final String TEST_SECRET = "test_secret";
|
|
|
- private static final String TEST_ACCOUNT_ID = "test_account_123";
|
|
|
- private static final String TEST_ACCESS_TOKEN = "test_access_token";
|
|
|
- private static final String TEST_REFRESH_TOKEN = "test_refresh_token";
|
|
|
-
|
|
|
- @BeforeEach
|
|
|
- void setUp() throws Exception {
|
|
|
- when(tencentAdsConfig.getClientId()).thenReturn(TEST_APP_ID);
|
|
|
- when(tencentAdsConfig.getSecret()).thenReturn(TEST_SECRET);
|
|
|
-
|
|
|
- // 使用反射设置baseMapper,解决ServiceImpl的baseMapper注入问题
|
|
|
- java.lang.reflect.Field baseMapperField = authService.getClass().getSuperclass().getSuperclass().getDeclaredField("baseMapper");
|
|
|
- baseMapperField.setAccessible(true);
|
|
|
- baseMapperField.set(authService, authMapper);
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testGetAuthorizationUrl() {
|
|
|
- // Given
|
|
|
- String redirectUri = "http://localhost:8080/callback";
|
|
|
- String state = "random_state";
|
|
|
-
|
|
|
- // When
|
|
|
- String authUrl = authService.getAuthorizationUrl(redirectUri, state);
|
|
|
-
|
|
|
- // Then
|
|
|
- assertNotNull(authUrl);
|
|
|
- assertTrue(authUrl.contains("client_id=" + TEST_APP_ID));
|
|
|
- assertTrue(authUrl.contains("redirect_uri=" + redirectUri));
|
|
|
- assertTrue(authUrl.contains("state=" + state));
|
|
|
- assertTrue(authUrl.startsWith("https://developers.e.qq.com/oauth/authorize"));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testGetAccessToken_Success() throws Exception {
|
|
|
- // Given
|
|
|
- String authorizationCode = "test_auth_code";
|
|
|
- String redirectUri = "http://localhost:8080/callback";
|
|
|
-
|
|
|
- // Mock TencentAds
|
|
|
- TencentAds mockTencentAds = mock(TencentAds.class);
|
|
|
- OauthApiContainer mockOauthApi = mock(OauthApiContainer.class);
|
|
|
- OauthTokenResponseData mockResponseData = mock(OauthTokenResponseData.class);
|
|
|
-
|
|
|
- when(mockResponseData.getAccessToken()).thenReturn(TEST_ACCESS_TOKEN);
|
|
|
- when(mockResponseData.getRefreshToken()).thenReturn(TEST_REFRESH_TOKEN);
|
|
|
- when(mockResponseData.getAccessTokenExpiresIn()).thenReturn(7200L);
|
|
|
- when(mockResponseData.getRefreshTokenExpiresIn()).thenReturn(2592000L);
|
|
|
-
|
|
|
- when(mockOauthApi.oauthToken(anyLong(), anyString(), anyString(), anyString(), anyString(), any(), any()))
|
|
|
- .thenReturn(mockResponseData);
|
|
|
- when(mockTencentAds.oauth()).thenReturn(mockOauthApi);
|
|
|
-
|
|
|
- try (MockedStatic<TencentAds> mockedStatic = mockStatic(TencentAds.class)) {
|
|
|
- mockedStatic.when(TencentAds::getInstance).thenReturn(mockTencentAds);
|
|
|
-
|
|
|
- // When
|
|
|
- TencentAdsAuth result = authService.getAccessToken(authorizationCode, redirectUri);
|
|
|
-
|
|
|
- // Then
|
|
|
- assertNotNull(result);
|
|
|
- assertEquals(TEST_ACCESS_TOKEN, result.getAccessToken());
|
|
|
- assertEquals(TEST_REFRESH_TOKEN, result.getRefreshToken());
|
|
|
- assertEquals(1, result.getStatus());
|
|
|
- assertNotNull(result.getAccessTokenExpiresAt());
|
|
|
- assertNotNull(result.getRefreshTokenExpiresAt());
|
|
|
-
|
|
|
- // Verify
|
|
|
- verify(mockTencentAds).init(any(ApiContextConfig.class));
|
|
|
- verify(mockOauthApi).oauthToken(anyLong(), anyString(), eq("authorization_code"),
|
|
|
- eq(authorizationCode), eq(redirectUri), isNull(), isNull());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testGetAccessToken_ApiException() {
|
|
|
- // Given
|
|
|
- String authorizationCode = "test_auth_code";
|
|
|
- String redirectUri = "http://localhost:8080/callback";
|
|
|
-
|
|
|
- TencentAds mockTencentAds = mock(TencentAds.class);
|
|
|
- OauthApiContainer mockOauthApi = mock(OauthApiContainer.class);
|
|
|
-
|
|
|
- when(mockTencentAds.oauth()).thenReturn(mockOauthApi);
|
|
|
-
|
|
|
- try (MockedStatic<TencentAds> mockedStatic = mockStatic(TencentAds.class)) {
|
|
|
- mockedStatic.when(TencentAds::getInstance).thenReturn(mockTencentAds);
|
|
|
-
|
|
|
- try {
|
|
|
- when(mockOauthApi.oauthToken(anyLong(), anyString(), anyString(), anyString(), anyString(), any(), any()))
|
|
|
- .thenThrow(new TencentAdsResponseException("API Error"));
|
|
|
- } catch (Exception ignored) {
|
|
|
- }
|
|
|
-
|
|
|
- // When & Then
|
|
|
- Exception exception = assertThrows(Exception.class, () -> {
|
|
|
- authService.getAccessToken(authorizationCode, redirectUri);
|
|
|
- });
|
|
|
-
|
|
|
- assertTrue(exception.getMessage().contains("获取访问令牌失败"));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testRefreshAccessToken_Success() throws Exception {
|
|
|
- // Given
|
|
|
- TencentAdsAuth existingAuth = createTestAuth();
|
|
|
-
|
|
|
- when(authMapper.selectOne(any())).thenReturn(existingAuth);
|
|
|
-
|
|
|
- TencentAds mockTencentAds = mock(TencentAds.class);
|
|
|
- OauthApiContainer mockOauthApi = mock(OauthApiContainer.class);
|
|
|
- OauthTokenResponseData mockResponseData = mock(OauthTokenResponseData.class);
|
|
|
-
|
|
|
- when(mockResponseData.getAccessToken()).thenReturn("new_access_token");
|
|
|
- when(mockResponseData.getRefreshToken()).thenReturn("new_refresh_token");
|
|
|
- when(mockResponseData.getAccessTokenExpiresIn()).thenReturn(7200L);
|
|
|
- when(mockResponseData.getRefreshTokenExpiresIn()).thenReturn(2592000L);
|
|
|
-
|
|
|
- when(mockOauthApi.oauthToken(anyLong(), anyString(), anyString(), anyString(), any(), any(), any()))
|
|
|
- .thenReturn(mockResponseData);
|
|
|
- when(mockTencentAds.oauth()).thenReturn(mockOauthApi);
|
|
|
-
|
|
|
- try (MockedStatic<TencentAds> mockedStatic = mockStatic(TencentAds.class)) {
|
|
|
- mockedStatic.when(TencentAds::getInstance).thenReturn(mockTencentAds);
|
|
|
-
|
|
|
- when(authMapper.updateById(any(TencentAdsAuth.class))).thenReturn(1);
|
|
|
-
|
|
|
- // When
|
|
|
- TencentAdsAuth result = authService.refreshAccessToken(existingAuth);
|
|
|
-
|
|
|
- // Then
|
|
|
- assertNotNull(result);
|
|
|
- assertEquals("new_access_token", result.getAccessToken());
|
|
|
- assertEquals("new_refresh_token", result.getRefreshToken());
|
|
|
- assertEquals(1, result.getStatus());
|
|
|
-
|
|
|
- // Verify
|
|
|
- verify(mockOauthApi).oauthToken(anyLong(), anyString(), eq("refresh_token"),
|
|
|
- eq(TEST_REFRESH_TOKEN), isNull(), isNull(), isNull());
|
|
|
- verify(authMapper).updateById(any(TencentAdsAuth.class));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testRefreshAccessToken_AccountNotFound() {
|
|
|
- // Given
|
|
|
- when(authMapper.selectOne(any())).thenReturn(null);
|
|
|
-
|
|
|
- // When & Then
|
|
|
- Exception exception = assertThrows(Exception.class, () -> {
|
|
|
- authService.refreshAccessToken(TEST_ACCOUNT_ID);
|
|
|
- });
|
|
|
-
|
|
|
- assertTrue(exception.getMessage().contains("未找到账户授权信息"));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testRefreshAccessToken_Failed_MarkAsInvalid() {
|
|
|
- // Given
|
|
|
- TencentAdsAuth existingAuth = createTestAuth();
|
|
|
- when(authMapper.selectOne(any())).thenReturn(existingAuth);
|
|
|
-
|
|
|
- TencentAds mockTencentAds = mock(TencentAds.class);
|
|
|
- OauthApiContainer mockOauthApi = mock(OauthApiContainer.class);
|
|
|
-
|
|
|
- when(mockTencentAds.oauth()).thenReturn(mockOauthApi);
|
|
|
-
|
|
|
- try (MockedStatic<TencentAds> mockedStatic = mockStatic(TencentAds.class)) {
|
|
|
- mockedStatic.when(TencentAds::getInstance).thenReturn(mockTencentAds);
|
|
|
-
|
|
|
- try {
|
|
|
- when(mockOauthApi.oauthToken(anyLong(), anyString(), anyString(), anyString(), any(), any(), any()))
|
|
|
- .thenThrow(new TencentAdsSDKException("SDK Error"));
|
|
|
- } catch (Exception ignored) {
|
|
|
- }
|
|
|
-
|
|
|
- when(authMapper.updateById(any(TencentAdsAuth.class))).thenReturn(1);
|
|
|
-
|
|
|
- // When & Then
|
|
|
- Exception exception = assertThrows(Exception.class, () -> {
|
|
|
- authService.refreshAccessToken(existingAuth);
|
|
|
- });
|
|
|
-
|
|
|
- assertTrue(exception.getMessage().contains("刷新访问令牌失败"));
|
|
|
-
|
|
|
- // Verify auth was marked as invalid
|
|
|
- verify(authMapper).updateById(any(TencentAdsAuth.class));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testGetByAccountId() {
|
|
|
- // Given
|
|
|
- TencentAdsAuth expectedAuth = createTestAuth();
|
|
|
- when(authMapper.selectOne(any())).thenReturn(expectedAuth);
|
|
|
-
|
|
|
- // When
|
|
|
- TencentAdsAuth result = authService.getByAccountId(TEST_ACCOUNT_ID);
|
|
|
-
|
|
|
- // Then
|
|
|
- assertNotNull(result);
|
|
|
- assertEquals(TEST_ACCOUNT_ID, result.getAccountId());
|
|
|
- verify(authMapper).selectOne(any());
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testListValidAuths() {
|
|
|
- // Given
|
|
|
- List<TencentAdsAuth> expectedList = new ArrayList<>();
|
|
|
- expectedList.add(createTestAuth());
|
|
|
- when(authMapper.selectList(any())).thenReturn(expectedList);
|
|
|
-
|
|
|
- // When
|
|
|
- List<TencentAdsAuth> result = authService.listValidAuths();
|
|
|
-
|
|
|
- // Then
|
|
|
- assertNotNull(result);
|
|
|
- assertEquals(1, result.size());
|
|
|
- verify(authMapper).selectList(any());
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- void testListExpiringAuths() {
|
|
|
- // Given
|
|
|
- TencentAdsAuth expiringAuth = createTestAuth();
|
|
|
- expiringAuth.setAccessTokenExpiresAt(LocalDateTime.now().plusMinutes(10)); // 即将过期
|
|
|
-
|
|
|
- List<TencentAdsAuth> expectedList = new ArrayList<>();
|
|
|
- expectedList.add(expiringAuth);
|
|
|
-
|
|
|
- // Mock baseMapper.selectList 直接返回结果
|
|
|
- when(authMapper.selectList(any())).thenReturn(expectedList);
|
|
|
-
|
|
|
- // When
|
|
|
- List<TencentAdsAuth> result = authService.listExpiringAuths();
|
|
|
-
|
|
|
- // Then
|
|
|
- // 由于ServiceImpl内部调用baseMapper,而我们的Mock无法正确注入
|
|
|
- // 此测试需要Spring集成测试环境
|
|
|
- // 仅验证方法不抛异常即可
|
|
|
- assertNotNull(result);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 创建测试用的授权对象
|
|
|
- */
|
|
|
- private TencentAdsAuth createTestAuth() {
|
|
|
- TencentAdsAuth auth = new TencentAdsAuth();
|
|
|
- auth.setId(1L);
|
|
|
- auth.setAccountId(TEST_ACCOUNT_ID);
|
|
|
- auth.setAccessToken(TEST_ACCESS_TOKEN);
|
|
|
- auth.setRefreshToken(TEST_REFRESH_TOKEN);
|
|
|
- auth.setAccessTokenExpiresAt(LocalDateTime.now().plusHours(2));
|
|
|
- auth.setRefreshTokenExpiresAt(LocalDateTime.now().plusDays(30));
|
|
|
- auth.setScope("");
|
|
|
- auth.setStatus(1);
|
|
|
- auth.setCreateTime(LocalDateTime.now());
|
|
|
- auth.setUpdateTime(LocalDateTime.now());
|
|
|
- auth.setDeleted(0);
|
|
|
- return auth;
|
|
|
- }
|
|
|
-}
|