test: JwtHandlerTest 코틀린 전환

This commit is contained in:
이상진 2025-07-13 20:52:37 +09:00
parent 227e2999b4
commit 44005fbdd7
2 changed files with 61 additions and 118 deletions

View File

@ -1,118 +0,0 @@
package roomescape.global.auth.jwt;
import static roomescape.system.exception.ErrorType.*;
import java.util.Date;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.jdbc.Sql;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.restassured.RestAssured;
import roomescape.system.auth.infrastructure.jwt.JwtHandler;
import roomescape.system.exception.ErrorType;
import roomescape.system.exception.RoomEscapeException;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Sql(scripts = "/truncate.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
class JwtHandlerTest {
@Autowired
private JwtHandler jwtHandler;
@Value("${security.jwt.token.secret-key}")
private String secretKey;
@LocalServerPort
private int port;
@BeforeEach
void setUp() {
RestAssured.port = port;
}
@Test
@DisplayName("토큰이 만료되면 401 Unauthorized 를 발생시킨다.")
void jwtExpired() {
//given
Date date = new Date();
Date expiredAt = new Date(date.getTime() - 1);
String accessToken = Jwts.builder()
.claim("memberId", 1L)
.setIssuedAt(date)
.setExpiration(expiredAt)
.signWith(SignatureAlgorithm.HS256, secretKey.getBytes())
.compact();
// when & then
Assertions.assertThatThrownBy(() -> jwtHandler.getMemberIdFromToken(accessToken))
.isInstanceOf(RoomEscapeException.class)
.hasMessage(EXPIRED_TOKEN.getDescription());
}
@Test
@DisplayName("지원하지 않는 토큰이면 401 Unauthorized 를 발생시킨다.")
void jwtMalformed() {
// given
Date date = new Date();
Date expiredAt = new Date(date.getTime() + 100000);
String accessToken = Jwts.builder()
.claim("memberId", 1L)
.setIssuedAt(date)
.setExpiration(expiredAt)
.signWith(SignatureAlgorithm.HS256, secretKey.getBytes())
.compact();
String[] splitAccessToken = accessToken.split("\\.");
String unsupportedAccessToken = splitAccessToken[0] + "." + splitAccessToken[1];
// when & then
Assertions.assertThatThrownBy(() -> jwtHandler.getMemberIdFromToken(unsupportedAccessToken))
.isInstanceOf(RoomEscapeException.class)
.hasMessage(ErrorType.MALFORMED_TOKEN.getDescription());
}
@Test
@DisplayName("토큰의 Signature 가 잘못되었다면 401 Unauthorized 를 발생시킨다.")
void jwtInvalidSignature() {
// given
Date date = new Date();
Date expiredAt = new Date(date.getTime() + 100000);
String invalidSecretKey = secretKey.substring(1);
String accessToken = Jwts.builder()
.claim("memberId", 1L)
.setIssuedAt(date)
.setExpiration(expiredAt)
.signWith(SignatureAlgorithm.HS256, invalidSecretKey.getBytes()) // 기존은 HS256 알고리즘
.compact();
// when & then
Assertions.assertThatThrownBy(() -> jwtHandler.getMemberIdFromToken(accessToken))
.isInstanceOf(RoomEscapeException.class)
.hasMessage(ErrorType.INVALID_SIGNATURE_TOKEN.getDescription());
}
@Test
@DisplayName("토큰이 공백값이라면 401 Unauthorized 를 발생시킨다.")
void jwtIllegal() {
// given
String accessToken = "";
// when & then
Assertions.assertThatThrownBy(() -> jwtHandler.getMemberIdFromToken(accessToken))
.isInstanceOf(RoomEscapeException.class)
.hasMessage(ErrorType.ILLEGAL_TOKEN.getDescription());
}
}

View File

@ -0,0 +1,61 @@
package roomescape.system.auth.infrastructure.jwt
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import roomescape.common.JwtFixture
import roomescape.system.exception.ErrorType
import roomescape.system.exception.RoomEscapeException
import java.util.*
import kotlin.random.Random
class JwtHandlerTest : FunSpec({
context("JWT 토큰 조회") {
val memberId = Random.nextLong()
val jwtHandler: JwtHandler = JwtFixture.create()
test("토큰에서 멤버 ID를 올바르게 추출한다.") {
val token = jwtHandler.createToken(memberId)
val extractedMemberId = jwtHandler.getMemberIdFromToken(token)
extractedMemberId shouldBe memberId
}
test("만료된 토큰이면 예외를 던진다.") {
// given
val expirationTime = 0L
val shortExpirationTimeJwtHandler: JwtHandler = JwtFixture.create(expirationTime = expirationTime)
val token = shortExpirationTimeJwtHandler.createToken(memberId)
Thread.sleep(expirationTime) // 만료 시간 이후로 대기
// when & then
shouldThrow<RoomEscapeException> {
shortExpirationTimeJwtHandler.getMemberIdFromToken(token)
}.errorType shouldBe ErrorType.EXPIRED_TOKEN
}
test("토큰이 빈 값이면 예외를 던진다.") {
shouldThrow<RoomEscapeException> {
jwtHandler.getMemberIdFromToken("")
}.errorType shouldBe ErrorType.INVALID_TOKEN
}
test("시크릿 키가 잘못된 경우 예외를 던진다.") {
val now: Date = Date()
val invalidSignatureToken: String = Jwts.builder()
.claim("memberId", memberId)
.setIssuedAt(now)
.setExpiration(Date(now.time + JwtFixture.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, JwtFixture.SECRET_KEY.substring(1).toByteArray())
.compact()
shouldThrow<RoomEscapeException> {
jwtHandler.getMemberIdFromToken(invalidSignatureToken)
}.errorType shouldBe ErrorType.INVALID_SIGNATURE_TOKEN
}
}
})