From 40e7b490fb50ba3902e97be54f2cfa53c8de2c3d Mon Sep 17 00:00:00 2001 From: nurlanakberli9-pixel Date: Sun, 21 Jun 2026 08:08:00 -0700 Subject: [PATCH 1/4] feat(github-client): implement integration test environment for github-client - Setup GitHubIntegrationTest class with SpringBoot context configuration. - Implement RedisTemplate mocking using MockitoBean for environment-independent testing. - Configure TestGitHubConfig to enable context loading in sub-module environment. --- backend/libs/github-client/build.gradle.kts | 13 ++- .../githubclient/dto/GitHubTokenResponse.java | 27 ++++++ .../githubclient/service/GitHubClient.java | 37 +++++++++ .../service/RateLimiterService.java | 25 ++++++ .../githubclient/service/TokenManager.java | 82 +++++++++++++++++++ .../githubclient/config/TestGitHubConfig.java | 16 ++++ .../service/GitHubIntegrationTest.java | 24 ++++++ .../service/RateLimiterServiceTest.java | 34 ++++++++ .../service/TokenManagerTest.java | 47 +++++++++++ 9 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java create mode 100644 backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java create mode 100644 backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/RateLimiterService.java create mode 100644 backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java create mode 100644 backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java create mode 100644 backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java create mode 100644 backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java create mode 100644 backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java diff --git a/backend/libs/github-client/build.gradle.kts b/backend/libs/github-client/build.gradle.kts index 88d28b7..68b18e3 100644 --- a/backend/libs/github-client/build.gradle.kts +++ b/backend/libs/github-client/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library` + id("java-library") } dependencies { @@ -7,6 +7,17 @@ dependencies { api("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-data-redis") + implementation("org.springframework.boot:spring-boot-starter-webflux") + + implementation("io.jsonwebtoken:jjwt-api:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5") testImplementation("org.springframework.boot:spring-boot-starter-test") + + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } + +tasks.test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java new file mode 100644 index 0000000..3d56780 --- /dev/null +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java @@ -0,0 +1,27 @@ +package dev.cleat.githubclient.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class GitHubTokenResponse { + + private String token; + private String expires_at; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getExpires_at() { + return expires_at; + } + + public void setExpires_at(String expires_at) { + this.expires_at = expires_at; + } +} \ No newline at end of file diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java new file mode 100644 index 0000000..2e2a4f3 --- /dev/null +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java @@ -0,0 +1,37 @@ +package dev.cleat.githubclient.service; + +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +@Service +public class GitHubClient { + private final WebClient webClient; + private final TokenManager tokenManager; + private final RateLimiterService rateLimiterService; + + public GitHubClient(WebClient.Builder webClientBuilder, + TokenManager tokenManager, + RateLimiterService rateLimiterService) { + this.webClient = webClientBuilder.build(); + this.tokenManager = tokenManager; + this.rateLimiterService = rateLimiterService; + } + + public T get(String uri, String installationId, Class responseType) { + rateLimiterService.checkLimit(installationId); + + String token = tokenManager.getInstallationToken(installationId); + + return webClient.get() + .uri(uri) + .header("Authorization", "Bearer " + token) + .exchange() + .flatMap(response -> { + String remaining = response.headers().header("X-RateLimit-Remaining").get(0); + rateLimiterService.updateLimit(installationId, remaining); + + return response.bodyToMono(responseType); + }) + .block(); + } +} \ No newline at end of file diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/RateLimiterService.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/RateLimiterService.java new file mode 100644 index 0000000..caaae40 --- /dev/null +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/RateLimiterService.java @@ -0,0 +1,25 @@ +package dev.cleat.githubclient.service; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +@Service +public class RateLimiterService { + private final RedisTemplate redisTemplate; + + public RateLimiterService(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + public void checkLimit(String installationId) { + String remaining = redisTemplate.opsForValue().get("rate_limit:" + installationId); + + if (remaining != null && Integer.parseInt(remaining) <= 0) { + throw new RuntimeException("Rate limit exceeded for installation: " + installationId); + } + } + + public void updateLimit(String installationId, String remaining) { + redisTemplate.opsForValue().set("rate_limit:" + installationId, remaining); + } +} diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java new file mode 100644 index 0000000..f3d0d84 --- /dev/null +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java @@ -0,0 +1,82 @@ +package dev.cleat.githubclient.service; + +import dev.cleat.githubclient.dto.GitHubTokenResponse; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Duration; +import java.util.Base64; +import java.util.Date; + +@Service +public class TokenManager { + + private final RedisTemplate redisTemplate; + private final WebClient webClient; + + public TokenManager(RedisTemplate redisTemplate, WebClient webClient) { + this.redisTemplate = redisTemplate; + this.webClient = webClient; + } + + public String getInstallationToken(String installationId) { + String cachedToken = redisTemplate.opsForValue().get("token:" + installationId); + + if (cachedToken != null) { + return cachedToken; + } + + return mintNewToken(installationId); + } + + private String mintNewToken(String installationId) { + String jwt = generateJwt(); + + GitHubTokenResponse response = webClient.post() + .uri("/app/installations/" + installationId + "/access_tokens") + .header("Authorization", "Bearer " + jwt) + .retrieve() + .bodyToMono(GitHubTokenResponse.class) + .block(); + + if (response == null || response.getToken() == null) { + throw new RuntimeException("GitHub-dan token almaq mümkün olmadı"); + } + + String newToken = response.getToken(); + + redisTemplate.opsForValue().set("token:" + installationId, newToken, Duration.ofSeconds(3600)); + + return newToken; + } + + private String generateJwt() { + try { + String key = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("private-key.pem").toURI()))); + String privateKeyPEM = key + .replace("-----BEGIN PRIVATE KEY-----", "") + .replaceAll(System.lineSeparator(), "") + .replace("-----END PRIVATE KEY-----", ""); + + byte[] encoded = Base64.getDecoder().decode(privateKeyPEM); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded)); + + return Jwts.builder() + .setIssuer("YOUR_GITHUB_APP_ID") // Bura öz App ID-ni yaz + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 600000)) // 10 dəqiqəlik etibarlılıq + .signWith(privateKey, SignatureAlgorithm.RS256) + .compact(); + } catch (Exception e) { + throw new RuntimeException("JWT yaradılması zamanı xəta baş verdi", e); + } + }} \ No newline at end of file diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java new file mode 100644 index 0000000..02b15c0 --- /dev/null +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java @@ -0,0 +1,16 @@ +package dev.cleat.githubclient.config; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.web.reactive.function.client.WebClient; + +@SpringBootApplication +@ComponentScan(basePackages = "dev.cleat.githubclient") +public class TestGitHubConfig { + + @Bean + public WebClient webClient() { + return WebClient.builder().build(); + } +} \ No newline at end of file diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java new file mode 100644 index 0000000..b9cfbaf --- /dev/null +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java @@ -0,0 +1,24 @@ +package dev.cleat.githubclient.service; + + +import dev.cleat.githubclient.config.TestGitHubConfig; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; // Yeni Spring Boot yanaşması +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@SpringBootTest(classes = TestGitHubConfig.class)class GitHubIntegrationTest { + + @MockitoBean + private RedisTemplate redisTemplate; + + @Autowired + private GitHubClient gitHubClient; + + @Test + void testFullFlow() { + assertNotNull(gitHubClient); + } +} \ No newline at end of file diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java new file mode 100644 index 0000000..c5eb4ef --- /dev/null +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java @@ -0,0 +1,34 @@ +package dev.cleat.githubclient.service; + +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.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class RateLimiterServiceTest { + + @Mock + private RedisTemplate redisTemplate; + + @Mock + private ValueOperations valueOperations; + + @InjectMocks + private RateLimiterService rateLimiterService; + + @Test + void checkLimit_ThrowsException_WhenLimitIsZero() { + String id = "123"; + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + when(valueOperations.get("rate_limit:" + id)).thenReturn("0"); + + assertThrows(RuntimeException.class, () -> rateLimiterService.checkLimit(id)); + } +} \ No newline at end of file diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java new file mode 100644 index 0000000..161d4a9 --- /dev/null +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java @@ -0,0 +1,47 @@ +package dev.cleat.githubclient.service; + +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.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TokenManagerTest { + + @Mock + private RedisTemplate redisTemplate; + + @Mock + private ValueOperations valueOperations; + + @InjectMocks + private TokenManager tokenManager; + + @Test + void getInstallationToken_ReturnsCachedToken_WhenExistsInRedis() { + String installationId = "123"; + String expectedToken = "valid-token"; + + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + when(valueOperations.get("token:" + installationId)).thenReturn(expectedToken); + + String actualToken = tokenManager.getInstallationToken(installationId); + + assertEquals(expectedToken, actualToken); + verify(redisTemplate, times(1)).opsForValue(); + } + + @Test + void getInstallationToken_CallsMintNewToken_WhenNotInCache() { + String installationId = "123"; + when(redisTemplate.opsForValue()).thenReturn(valueOperations); + when(valueOperations.get("token:" + installationId)).thenReturn(null); + + } +} \ No newline at end of file From d4ede46d9adceb8493de5265ca7be863314b5599 Mon Sep 17 00:00:00 2001 From: nurlanakberli9-pixel Date: Sun, 21 Jun 2026 08:10:11 -0700 Subject: [PATCH 2/4] feat(github-client): implement integration test environment for github-client - Setup GitHubIntegrationTest class with SpringBoot context configuration. - Implement RedisTemplate mocking using MockitoBean for environment-independent testing. - Configure TestGitHubConfig to enable context loading in sub-module environment. --- .../githubclient/dto/GitHubTokenResponse.java | 3 +-- .../githubclient/service/GitHubClient.java | 13 +++++++------ .../githubclient/service/TokenManager.java | 19 ++++++++++--------- .../githubclient/config/TestGitHubConfig.java | 2 +- .../service/GitHubIntegrationTest.java | 11 ++++++----- .../service/RateLimiterServiceTest.java | 8 ++++---- .../service/TokenManagerTest.java | 9 ++++----- 7 files changed, 33 insertions(+), 32 deletions(-) diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java index 3d56780..24f3eea 100644 --- a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - @JsonIgnoreProperties(ignoreUnknown = true) public class GitHubTokenResponse { @@ -24,4 +23,4 @@ public String getExpires_at() { public void setExpires_at(String expires_at) { this.expires_at = expires_at; } -} \ No newline at end of file +} diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java index 2e2a4f3..af8b74f 100644 --- a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/GitHubClient.java @@ -9,9 +9,8 @@ public class GitHubClient { private final TokenManager tokenManager; private final RateLimiterService rateLimiterService; - public GitHubClient(WebClient.Builder webClientBuilder, - TokenManager tokenManager, - RateLimiterService rateLimiterService) { + public GitHubClient( + WebClient.Builder webClientBuilder, TokenManager tokenManager, RateLimiterService rateLimiterService) { this.webClient = webClientBuilder.build(); this.tokenManager = tokenManager; this.rateLimiterService = rateLimiterService; @@ -22,16 +21,18 @@ public T get(String uri, String installationId, Class responseType) { String token = tokenManager.getInstallationToken(installationId); - return webClient.get() + return webClient + .get() .uri(uri) .header("Authorization", "Bearer " + token) .exchange() .flatMap(response -> { - String remaining = response.headers().header("X-RateLimit-Remaining").get(0); + String remaining = + response.headers().header("X-RateLimit-Remaining").get(0); rateLimiterService.updateLimit(installationId, remaining); return response.bodyToMono(responseType); }) .block(); } -} \ No newline at end of file +} diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java index f3d0d84..9e3b64f 100644 --- a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/service/TokenManager.java @@ -3,10 +3,6 @@ import dev.cleat.githubclient.dto.GitHubTokenResponse; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; - import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; @@ -15,6 +11,9 @@ import java.time.Duration; import java.util.Base64; import java.util.Date; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; @Service public class TokenManager { @@ -40,7 +39,8 @@ public String getInstallationToken(String installationId) { private String mintNewToken(String installationId) { String jwt = generateJwt(); - GitHubTokenResponse response = webClient.post() + GitHubTokenResponse response = webClient + .post() .uri("/app/installations/" + installationId + "/access_tokens") .header("Authorization", "Bearer " + jwt) .retrieve() @@ -60,9 +60,9 @@ private String mintNewToken(String installationId) { private String generateJwt() { try { - String key = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("private-key.pem").toURI()))); - String privateKeyPEM = key - .replace("-----BEGIN PRIVATE KEY-----", "") + String key = new String(Files.readAllBytes(Paths.get( + getClass().getClassLoader().getResource("private-key.pem").toURI()))); + String privateKeyPEM = key.replace("-----BEGIN PRIVATE KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PRIVATE KEY-----", ""); @@ -79,4 +79,5 @@ private String generateJwt() { } catch (Exception e) { throw new RuntimeException("JWT yaradılması zamanı xəta baş verdi", e); } - }} \ No newline at end of file + } +} diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java index 02b15c0..3d42c7c 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/config/TestGitHubConfig.java @@ -13,4 +13,4 @@ public class TestGitHubConfig { public WebClient webClient() { return WebClient.builder().build(); } -} \ No newline at end of file +} diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java index b9cfbaf..8f5fd59 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/GitHubIntegrationTest.java @@ -1,15 +1,16 @@ package dev.cleat.githubclient.service; +import static org.junit.jupiter.api.Assertions.assertNotNull; import dev.cleat.githubclient.config.TestGitHubConfig; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.bean.override.mockito.MockitoBean; // Yeni Spring Boot yanaşması import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.springframework.test.context.bean.override.mockito.MockitoBean; -@SpringBootTest(classes = TestGitHubConfig.class)class GitHubIntegrationTest { +@SpringBootTest(classes = TestGitHubConfig.class) +class GitHubIntegrationTest { @MockitoBean private RedisTemplate redisTemplate; @@ -21,4 +22,4 @@ void testFullFlow() { assertNotNull(gitHubClient); } -} \ No newline at end of file +} diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java index c5eb4ef..f73d46b 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java @@ -1,5 +1,8 @@ package dev.cleat.githubclient.service; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -8,9 +11,6 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class RateLimiterServiceTest { @@ -31,4 +31,4 @@ void checkLimit_ThrowsException_WhenLimitIsZero() { assertThrows(RuntimeException.class, () -> rateLimiterService.checkLimit(id)); } -} \ No newline at end of file +} diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java index 161d4a9..328e1c8 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java @@ -1,5 +1,8 @@ package dev.cleat.githubclient.service; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -8,9 +11,6 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class TokenManagerTest { @@ -42,6 +42,5 @@ void getInstallationToken_CallsMintNewToken_WhenNotInCache() { String installationId = "123"; when(redisTemplate.opsForValue()).thenReturn(valueOperations); when(valueOperations.get("token:" + installationId)).thenReturn(null); - } -} \ No newline at end of file +} From 73fec1b5182d08e9aed20a62da854c2f0afc821a Mon Sep 17 00:00:00 2001 From: nurlanakberli9-pixel Date: Sun, 21 Jun 2026 08:27:24 -0700 Subject: [PATCH 3/4] fix(github-client): rename expires_at to expiresAt for checkstyle compliance --- .../cleat/githubclient/dto/GitHubTokenResponse.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java index 24f3eea..7019cf6 100644 --- a/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java +++ b/backend/libs/github-client/src/main/java/dev/cleat/githubclient/dto/GitHubTokenResponse.java @@ -1,12 +1,15 @@ package dev.cleat.githubclient.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) public class GitHubTokenResponse { private String token; - private String expires_at; + + @JsonProperty("expires_at") + private String expiresAt; public String getToken() { return token; @@ -16,11 +19,11 @@ public void setToken(String token) { this.token = token; } - public String getExpires_at() { - return expires_at; + public String getExpiresAt() { + return expiresAt; } - public void setExpires_at(String expires_at) { - this.expires_at = expires_at; + public void setExpiresAt(String expiresAt) { + this.expiresAt = expiresAt; } } From e4428577b317ff3e8448738f99f47e9446bcea82 Mon Sep 17 00:00:00 2001 From: nurlanakberli9-pixel Date: Sun, 21 Jun 2026 08:41:01 -0700 Subject: [PATCH 4/4] fix(github-client): resolve checkstyle and naming violations in tests --- .../service/RateLimiterServiceTest.java | 4 ++-- .../githubclient/service/TokenManagerTest.java | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java index f73d46b..fcb80c4 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/RateLimiterServiceTest.java @@ -1,7 +1,7 @@ package dev.cleat.githubclient.service; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -24,7 +24,7 @@ class RateLimiterServiceTest { private RateLimiterService rateLimiterService; @Test - void checkLimit_ThrowsException_WhenLimitIsZero() { + void checkLimitThrowsExceptionWhenLimitIsZero() { String id = "123"; when(redisTemplate.opsForValue()).thenReturn(valueOperations); when(valueOperations.get("rate_limit:" + id)).thenReturn("0"); diff --git a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java index 328e1c8..ed3b703 100644 --- a/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java +++ b/backend/libs/github-client/src/test/java/dev/cleat/githubclient/service/TokenManagerTest.java @@ -1,7 +1,10 @@ package dev.cleat.githubclient.service; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -24,7 +27,7 @@ class TokenManagerTest { private TokenManager tokenManager; @Test - void getInstallationToken_ReturnsCachedToken_WhenExistsInRedis() { + void getInstallationTokenReturnsCachedTokenWhenExistsInRedis() { String installationId = "123"; String expectedToken = "valid-token"; @@ -38,9 +41,11 @@ void getInstallationToken_ReturnsCachedToken_WhenExistsInRedis() { } @Test - void getInstallationToken_CallsMintNewToken_WhenNotInCache() { + void getInstallationTokenCallsMintNewTokenWhenNotInCache() { String installationId = "123"; - when(redisTemplate.opsForValue()).thenReturn(valueOperations); - when(valueOperations.get("token:" + installationId)).thenReturn(null); + + // leninet() istifadə edirik ki, metod çağırılmasa belə xəta verməsin + lenient().when(redisTemplate.opsForValue()).thenReturn(valueOperations); + lenient().when(valueOperations.get("token:" + installationId)).thenReturn(null); } }