diff --git a/src/main/java/org/runimo/runimo/auth/filters/JwtAuthenticationFilter.java b/src/main/java/org/runimo/runimo/auth/filters/JwtAuthenticationFilter.java index 7813dc01..c8aef7a8 100644 --- a/src/main/java/org/runimo/runimo/auth/filters/JwtAuthenticationFilter.java +++ b/src/main/java/org/runimo/runimo/auth/filters/JwtAuthenticationFilter.java @@ -8,14 +8,16 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Collections; +import java.util.List; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.runimo.runimo.auth.jwt.JwtResolver; +import org.runimo.runimo.auth.jwt.UserDetail; import org.runimo.runimo.common.response.ErrorResponse; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -27,6 +29,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private static final String AUTH_HEADER = "Authorization"; private static final String AUTH_PREFIX = "Bearer "; + private static final String ROLE_PREFIX = "ROLE_"; private static final int TOKEN_PREFIX_LENGTH = 7; private final JwtResolver jwtResolver; private final ObjectMapper objectMapper = new ObjectMapper(); @@ -64,11 +67,11 @@ private String extractToken(HttpServletRequest request) { private boolean processToken(String jwtToken, HttpServletResponse response) throws IOException { try { - String userId = jwtResolver.getUserIdFromJwtToken(jwtToken); + UserDetail userDetail = jwtResolver.getUserDetailFromJwtToken(jwtToken); Authentication authentication = new UsernamePasswordAuthenticationToken( - userId, + userDetail.userId(), null, - Collections.emptyList() + List.of(new SimpleGrantedAuthority(ROLE_PREFIX + userDetail.role())) ); SecurityContextHolder.getContext().setAuthentication(authentication); return true; diff --git a/src/main/java/org/runimo/runimo/auth/jwt/JwtResolver.java b/src/main/java/org/runimo/runimo/auth/jwt/JwtResolver.java index a5ed8d3c..b622653a 100644 --- a/src/main/java/org/runimo/runimo/auth/jwt/JwtResolver.java +++ b/src/main/java/org/runimo/runimo/auth/jwt/JwtResolver.java @@ -21,6 +21,13 @@ public DecodedJWT verifyJwtToken(String token) throws JWTVerificationException { return JWT.require(Algorithm.HMAC256(jwtSecret)).withIssuer(ISSUER).build().verify(token); } + public UserDetail getUserDetailFromJwtToken(String token) throws JWTVerificationException { + DecodedJWT jwt = verifyJwtToken(token); + String userId = jwt.getSubject(); + String role = jwt.getClaim("role").asString(); + return new UserDetail(userId, role); + } + public String getUserIdFromJwtToken(String token) throws JWTVerificationException { DecodedJWT jwt = verifyJwtToken(token); return jwt.getSubject(); diff --git a/src/main/java/org/runimo/runimo/auth/jwt/JwtTokenFactory.java b/src/main/java/org/runimo/runimo/auth/jwt/JwtTokenFactory.java index 3a7205b5..c9474157 100644 --- a/src/main/java/org/runimo/runimo/auth/jwt/JwtTokenFactory.java +++ b/src/main/java/org/runimo/runimo/auth/jwt/JwtTokenFactory.java @@ -24,15 +24,16 @@ public JwtTokenFactory(String jwtSecret, long jwtExpiration, long jwtRefreshExpi this.tempJwtExpiration = tempJwtExpiration; } - public String generateAccessToken(String userPublicId) { + public String generateAccessToken(User user) { Date now = new Date(); Date expiryDate = new Date(now.getTime() + jwtExpiration); return JWT.create() - .withSubject(userPublicId) + .withSubject(user.getPublicId()) .withIssuedAt(now) .withExpiresAt(expiryDate) .withIssuer(ISSUER) + .withClaim("role", user.getRole().name()) .sign(Algorithm.HMAC256(jwtSecret)); } @@ -65,7 +66,7 @@ public String generateSignupTemporalToken(String providerId, SocialProvider soci } public TokenPair generateTokenPair(User user) { - String accessToken = generateAccessToken(user.getPublicId()); + String accessToken = generateAccessToken(user); String refreshToken = generateRefreshToken(user.getPublicId()); return new TokenPair(accessToken, refreshToken); } diff --git a/src/main/java/org/runimo/runimo/auth/jwt/UserDetail.java b/src/main/java/org/runimo/runimo/auth/jwt/UserDetail.java new file mode 100644 index 00000000..9da5a7d3 --- /dev/null +++ b/src/main/java/org/runimo/runimo/auth/jwt/UserDetail.java @@ -0,0 +1,8 @@ +package org.runimo.runimo.auth.jwt; + +public record UserDetail( + String userId, + String role +) { + +} diff --git a/src/main/java/org/runimo/runimo/auth/service/TokenRefreshService.java b/src/main/java/org/runimo/runimo/auth/service/TokenRefreshService.java index eb930353..3cf5c76e 100644 --- a/src/main/java/org/runimo/runimo/auth/service/TokenRefreshService.java +++ b/src/main/java/org/runimo/runimo/auth/service/TokenRefreshService.java @@ -45,7 +45,7 @@ public TokenPair refreshAccessToken(String refreshToken) { throw UserJwtException.of(UserHttpResponseCode.TOKEN_INVALID); } - String newAccessToken = jwtTokenFactory.generateAccessToken(userPublicId); + String newAccessToken = jwtTokenFactory.generateAccessToken(user); return new TokenPair(newAccessToken, refreshToken); } } diff --git a/src/main/java/org/runimo/runimo/config/SecurityConfig.java b/src/main/java/org/runimo/runimo/config/SecurityConfig.java index 58c009e1..9229dd44 100644 --- a/src/main/java/org/runimo/runimo/config/SecurityConfig.java +++ b/src/main/java/org/runimo/runimo/config/SecurityConfig.java @@ -50,6 +50,7 @@ public SecurityFilterChain devSecurityFilterChain(HttpSecurity http) throws Exce .requestMatchers("/swagger-ui/**", "/swagger-ui.html", "/v3/api-docs/**") .permitAll() .requestMatchers(("/error")).permitAll() + .requestMatchers("/api/v1/users/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() ) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); diff --git a/src/main/java/org/runimo/runimo/user/domain/User.java b/src/main/java/org/runimo/runimo/user/domain/User.java index c1f86b7a..c203210b 100644 --- a/src/main/java/org/runimo/runimo/user/domain/User.java +++ b/src/main/java/org/runimo/runimo/user/domain/User.java @@ -37,6 +37,10 @@ public class User extends BaseEntity { @Column(name = "gender") @Enumerated(EnumType.STRING) private Gender gender; + @Column(name = "role", nullable = false) + @Enumerated(EnumType.STRING) + private UserRole role = UserRole.USER; + @Builder public User(String nickname, String imgUrl, Long totalDistanceInMeters, @@ -46,6 +50,7 @@ public User(String nickname, String imgUrl, Long totalDistanceInMeters, this.totalDistanceInMeters = totalDistanceInMeters != null ? totalDistanceInMeters : 0L; this.totalTimeInSeconds = totalTimeInSeconds != null ? totalTimeInSeconds : 0L; this.gender = gender; + this.role = role != null ? role : UserRole.USER; } public boolean checkUserFirstRun() { diff --git a/src/main/java/org/runimo/runimo/user/domain/UserRole.java b/src/main/java/org/runimo/runimo/user/domain/UserRole.java new file mode 100644 index 00000000..91d4fba7 --- /dev/null +++ b/src/main/java/org/runimo/runimo/user/domain/UserRole.java @@ -0,0 +1,6 @@ +package org.runimo.runimo.user.domain; + +public enum UserRole { + USER, + ADMIN +} diff --git a/src/main/resources/sql/schema.sql b/src/main/resources/sql/schema.sql index 4dde842d..dc2e3a27 100644 --- a/src/main/resources/sql/schema.sql +++ b/src/main/resources/sql/schema.sql @@ -29,6 +29,7 @@ CREATE TABLE `users` `total_time_in_seconds` BIGINT NOT NULL DEFAULT 0, `main_runimo_id` BIGINT, `gender` VARCHAR(24), + `role` VARCHAR(24) NOT NULL DEFAULT 'USER', `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -91,16 +92,16 @@ CREATE TABLE `signup_token` CREATE TABLE `running_record` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, `record_public_id` VARCHAR(255) NOT NULL, `title` VARCHAR(255), `description` VARCHAR(255), `img_url` VARCHAR(255), `started_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `end_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - `total_distance` INTEGER, - `pace_in_milli_seconds` INTEGER, + `total_distance` BIGINT, + `pace_in_milli_seconds` BIGINT, `is_rewarded` BOOLEAN, `pace_per_km` VARCHAR(10000), `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -110,7 +111,7 @@ CREATE TABLE `running_record` CREATE TABLE `item` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `item_code` VARCHAR(255) NOT NULL, `description` VARCHAR(255), @@ -126,7 +127,7 @@ CREATE TABLE `item` CREATE TABLE `egg_type` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(64) NOT NULL, `code` VARCHAR(64) NOT NULL, `required_distance_in_meters` BIGINT, @@ -139,11 +140,11 @@ CREATE TABLE `egg_type` CREATE TABLE `item_activity` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, - `activity_user_id` INTEGER NOT NULL, - `activity_item_id` INTEGER NOT NULL, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `activity_user_id` BIGINT NOT NULL, + `activity_item_id` BIGINT NOT NULL, `activity_event_type` VARCHAR(255) NOT NULL, - `quantity` INTEGER, + `quantity` BIGINT, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -152,9 +153,9 @@ CREATE TABLE `item_activity` CREATE TABLE `user_item` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, - `item_id` INTEGER NOT NULL, - `quantity` INTEGER NOT NULL, + `user_id` BIGINT NOT NULL, + `item_id` BIGINT NOT NULL, + `quantity` BIGINT NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -163,10 +164,10 @@ CREATE TABLE `user_item` CREATE TABLE `incubating_egg` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, - `egg_id` INTEGER NOT NULL, - `current_love_point_amount` INTEGER, - `hatch_require_amount` INTEGER, + `user_id` BIGINT NOT NULL, + `egg_id` BIGINT NOT NULL, + `current_love_point_amount` BIGINT, + `hatch_require_amount` BIGINT, `egg_status` VARCHAR(255), `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, diff --git a/src/test/java/org/runimo/runimo/TestConsts.java b/src/test/java/org/runimo/runimo/TestConsts.java new file mode 100644 index 00000000..f4676258 --- /dev/null +++ b/src/test/java/org/runimo/runimo/TestConsts.java @@ -0,0 +1,6 @@ +package org.runimo.runimo; + +public class TestConsts { + public static final String TEST_USER_UUID = "test-user-uuid-1"; + +} diff --git a/src/test/java/org/runimo/runimo/TokenUtils.java b/src/test/java/org/runimo/runimo/TokenUtils.java new file mode 100644 index 00000000..e982b4aa --- /dev/null +++ b/src/test/java/org/runimo/runimo/TokenUtils.java @@ -0,0 +1,55 @@ +package org.runimo.runimo; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import java.util.Date; +import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.user.domain.User; +import org.runimo.runimo.user.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class TokenUtils { + + private final static String AUTH_HEADER_PREFIX = "Bearer "; + private final static Long TEST_EXPIRATION_TIME = 1000L * 60 * 60 * 24 * 30; // 30 days + private final static String ISSUER = "RUNIMO_SERVICE"; + private final static String TEST_SECRET = "testSecret"; + @Autowired + private JwtTokenFactory jwtTokenFactory; + @Autowired + private UserRepository userRepository; + + + public String createTokenByUserPublicId(String publicId) { + User user = userRepository.findByPublicId(publicId) + .orElseThrow(() -> new IllegalStateException("테스트 유저가 존재하지 않습니다.")); + return AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(user); + } + + public String createTestOidcToken(String testPublicId) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + TEST_EXPIRATION_TIME); + + return JWT.create() + .withSubject(testPublicId) + .withIssuedAt(now) + .withExpiresAt(expiryDate) + .withIssuer(ISSUER) + .sign(Algorithm.HMAC256(TEST_SECRET)); + } + + public static String createTestOnlyToken(String testPublicId) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + TEST_EXPIRATION_TIME); + + return AUTH_HEADER_PREFIX + JWT.create() + .withSubject(testPublicId) + .withIssuedAt(now) + .withExpiresAt(expiryDate) + .withIssuer(ISSUER) + .withClaim("role", "USER") + .sign(Algorithm.HMAC256(TEST_SECRET)); + } +} diff --git a/src/test/java/org/runimo/runimo/auth/controller/AuthAcceptanceTest.java b/src/test/java/org/runimo/runimo/auth/controller/AuthAcceptanceTest.java index ac21e0ce..fe9e4d56 100644 --- a/src/test/java/org/runimo/runimo/auth/controller/AuthAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/auth/controller/AuthAcceptanceTest.java @@ -1,7 +1,8 @@ package org.runimo.runimo.auth.controller; import static io.restassured.RestAssured.given; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -15,7 +16,6 @@ import org.runimo.runimo.auth.domain.SignupToken; import org.runimo.runimo.auth.jwt.JwtTokenFactory; import org.runimo.runimo.auth.repository.SignupTokenRepository; - import org.runimo.runimo.auth.service.login.apple.AppleTokenVerifier; import org.runimo.runimo.auth.service.login.kakao.KakaoLoginHandler; import org.runimo.runimo.auth.service.login.kakao.KakaoTokenVerifier; diff --git a/src/test/java/org/runimo/runimo/auth/controller/AuthControllerTest.java b/src/test/java/org/runimo/runimo/auth/controller/AuthControllerTest.java index 7f649bdc..465b548a 100644 --- a/src/test/java/org/runimo/runimo/auth/controller/AuthControllerTest.java +++ b/src/test/java/org/runimo/runimo/auth/controller/AuthControllerTest.java @@ -28,8 +28,8 @@ import org.springframework.http.MediaType; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; - @ControllerTest(controllers = {AuthController.class}) + class AuthControllerTest { @Autowired @@ -56,6 +56,7 @@ class AuthControllerTest { @Autowired private ObjectMapper objectMapper; + @Test void 카카오_로그인_INVALID_401응답() throws Exception { // given diff --git a/src/test/java/org/runimo/runimo/auth/controller/TokenRefreshAcceptanceTest.java b/src/test/java/org/runimo/runimo/auth/controller/TokenRefreshAcceptanceTest.java index 2aab1e8b..7c2eaaf3 100644 --- a/src/test/java/org/runimo/runimo/auth/controller/TokenRefreshAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/auth/controller/TokenRefreshAcceptanceTest.java @@ -12,10 +12,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.runimo.runimo.CleanUpUtil; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.auth.controller.request.KakaoLoginRequest; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; -import org.runimo.runimo.auth.service.login.kakao.KakaoUserInfo; import org.runimo.runimo.auth.service.login.kakao.KakaoTokenVerifier; +import org.runimo.runimo.auth.service.login.kakao.KakaoUserInfo; import org.runimo.runimo.auth.test.TestAuthRequest; import org.runimo.runimo.user.UserFixtures; import org.runimo.runimo.user.domain.OAuthInfo; @@ -34,135 +34,131 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class TokenRefreshAcceptanceTest { - private static final String TEST_PROVIDER_ID = "test-provider-id"; - private static final String TEST_PUBLIC_ID = "test-public-id"; - - @LocalServerPort - private int port; - - @Autowired - private CleanUpUtil cleanUpUtil; - - @Autowired - private UserRepository userRepository; - - @Autowired - private ObjectMapper objectMapper; - - @Autowired - private OAuthInfoRepository oAuthInfoRepository; - - @MockitoBean - private KakaoTokenVerifier kakaoTokenVerifier; - - @Autowired - private JwtTokenFactory jwtTokenFactory; - - @BeforeEach - void setup() { - RestAssured.port = port; - cleanUpUtil.cleanUpUserInfos(); - - User user = UserFixtures.getDefaultUser(); - userRepository.save(user); - OAuthInfo oAuthInfo = OAuthInfo.builder() - .user(user) - .providerId(TEST_PROVIDER_ID) - .provider(SocialProvider.KAKAO) - .build(); - oAuthInfoRepository.save(oAuthInfo); - } - - - - @Test - void 로그인_후_토큰_갱신_성공_200() throws JsonProcessingException { - - String testOidcToken = jwtTokenFactory.generateAccessToken(TEST_PUBLIC_ID); - KakaoLoginRequest request = new KakaoLoginRequest(testOidcToken); - - Mockito.when(kakaoTokenVerifier.verifyToken(any(DecodedJWT.class))) - .thenReturn(new KakaoUserInfo(TEST_PROVIDER_ID)); - - // login - String refreshToken = given() - .header("Authorization", "Bearer test-access-token") - .contentType("application/json") - .body(objectMapper.writeValueAsString(request)) - .when() - .post("/api/v1/auth/kakao") - .then() - .log().all() - .statusCode(HttpStatus.OK.value()) - .extract() - .body().path("payload.refresh_token"); - - - given() - .contentType("application/json") - .header("Authorization", refreshToken) - .when() - .post("/api/v1/auth/refresh") - .then() - .statusCode(HttpStatus.OK.value()); - - } - - @Test - void 로그인_후_RefreshToken_오류_시_갱신_실패_403() throws JsonProcessingException { - - String testOidcToken = jwtTokenFactory.generateAccessToken(TEST_PUBLIC_ID); - KakaoLoginRequest request = new KakaoLoginRequest(testOidcToken); - - Mockito.when(kakaoTokenVerifier.verifyToken(any(DecodedJWT.class))) - .thenReturn(new KakaoUserInfo(TEST_PROVIDER_ID)); - - // login - String accessToken = given() - .header("Authorization", "Bearer test-access-token") - .contentType("application/json") - .body(objectMapper.writeValueAsString(request)) - .when() - .post("/api/v1/auth/kakao") - .then() - .log().all() - .statusCode(HttpStatus.OK.value()) - .extract() - .body().path("payload.access_token"); - - // 리프레쉬가 아니라 액세스토큰을 넘겨서 오류 상황을 재현 - given() - .contentType("application/json") - .header("Authorization", accessToken) - .when() - .post("/api/v1/auth/refresh") - .then() - .statusCode(HttpStatus.UNAUTHORIZED.value()); - - } - - @Test - void 테스트_로그인_후_리프레쉬_성공() throws JsonProcessingException { - TestAuthRequest request = new TestAuthRequest(1L); - String refreshToken = given() - .contentType("application/json") - .body(objectMapper.writeValueAsString(request)) - .when() - .post("/api/v1/auth/test/login") - .then() - .statusCode(HttpStatus.OK.value()) - .extract() - .path("payload.tokens.refresh_token"); - - given() - .header("Authorization", "Bearer " + refreshToken) - .when() - .post("/api/v1/auth/refresh") - .then() - .log().all() - .statusCode(HttpStatus.OK.value()) - .body("payload.access_token", notNullValue()) - .body("payload.refresh_token", notNullValue()); - } + private static final String TEST_PROVIDER_ID = "test-provider-id"; + private static final String TEST_PUBLIC_ID = "test-public-id"; + + @LocalServerPort + private int port; + + @Autowired + private CleanUpUtil cleanUpUtil; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private OAuthInfoRepository oAuthInfoRepository; + @MockitoBean + private KakaoTokenVerifier kakaoTokenVerifier; + @Autowired + private TokenUtils tokenUtils; + + @BeforeEach + void setup() { + RestAssured.port = port; + cleanUpUtil.cleanUpUserInfos(); + + User user = UserFixtures.getDefaultUser(); + userRepository.save(user); + OAuthInfo oAuthInfo = OAuthInfo.builder() + .user(user) + .providerId(TEST_PROVIDER_ID) + .provider(SocialProvider.KAKAO) + .build(); + oAuthInfoRepository.save(oAuthInfo); + } + + + @Test + void 로그인_후_토큰_갱신_성공_200() throws JsonProcessingException { + + String testOidcToken = tokenUtils.createTestOidcToken(TEST_PUBLIC_ID); + KakaoLoginRequest request = new KakaoLoginRequest(testOidcToken); + + Mockito.when(kakaoTokenVerifier.verifyToken(any(DecodedJWT.class))) + .thenReturn(new KakaoUserInfo(TEST_PROVIDER_ID)); + + // login + String refreshToken = given() + .header("Authorization", "Bearer test-access-token") + .contentType("application/json") + .body(objectMapper.writeValueAsString(request)) + .when() + .post("/api/v1/auth/kakao") + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .body().path("payload.refresh_token"); + + given() + .contentType("application/json") + .header("Authorization", refreshToken) + .when() + .post("/api/v1/auth/refresh") + .then() + .statusCode(HttpStatus.OK.value()); + + } + + @Test + void 로그인_후_RefreshToken_오류_시_갱신_실패_403() throws JsonProcessingException { + + String testOidcToken = tokenUtils.createTestOidcToken(TEST_PUBLIC_ID); + KakaoLoginRequest request = new KakaoLoginRequest(testOidcToken); + + Mockito.when(kakaoTokenVerifier.verifyToken(any(DecodedJWT.class))) + .thenReturn(new KakaoUserInfo(TEST_PROVIDER_ID)); + + // login + String accessToken = given() + .header("Authorization", "Bearer test-access-token") + .contentType("application/json") + .body(objectMapper.writeValueAsString(request)) + .when() + .post("/api/v1/auth/kakao") + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .body().path("payload.access_token"); + + // 리프레쉬가 아니라 액세스토큰을 넘겨서 오류 상황을 재현 + given() + .contentType("application/json") + .header("Authorization", accessToken) + .when() + .post("/api/v1/auth/refresh") + .then() + .statusCode(HttpStatus.UNAUTHORIZED.value()); + + } + + @Test + void 테스트_로그인_후_리프레쉬_성공() throws JsonProcessingException { + TestAuthRequest request = new TestAuthRequest(1L); + String refreshToken = given() + .contentType("application/json") + .body(objectMapper.writeValueAsString(request)) + .when() + .post("/api/v1/auth/test/login") + .then() + .statusCode(HttpStatus.OK.value()) + .extract() + .path("payload.tokens.refresh_token"); + + given() + .header("Authorization", "Bearer " + refreshToken) + .when() + .post("/api/v1/auth/refresh") + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .body("payload.access_token", notNullValue()) + .body("payload.refresh_token", notNullValue()); + } } diff --git a/src/test/java/org/runimo/runimo/configs/TestConfig.java b/src/test/java/org/runimo/runimo/configs/TestConfig.java index 54e6e9ed..dfce4d9e 100644 --- a/src/test/java/org/runimo/runimo/configs/TestConfig.java +++ b/src/test/java/org/runimo/runimo/configs/TestConfig.java @@ -4,17 +4,21 @@ import org.runimo.runimo.auth.jwt.JwtTokenFactory; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; @TestConfiguration public class TestConfig { - @Bean + private static final String TEST_SECRET = "testSecret"; + + @Primary public JwtTokenFactory jwtTokenFactory() { - return new JwtTokenFactory("testSecret", 100000L, 360000L, 60000L); + return new JwtTokenFactory(TEST_SECRET, 100000L, 360000L, 60000L); } @Bean + @Primary public JwtResolver jwtResolver() { - return new JwtResolver("testSecret"); + return new JwtResolver(TEST_SECRET); } } diff --git a/src/test/java/org/runimo/runimo/hatch/controller/HatchControllerTest.java b/src/test/java/org/runimo/runimo/hatch/controller/HatchControllerTest.java index cf9e2a96..e4b64a9b 100644 --- a/src/test/java/org/runimo/runimo/hatch/controller/HatchControllerTest.java +++ b/src/test/java/org/runimo/runimo/hatch/controller/HatchControllerTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.startsWith; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.RestAssured; @@ -13,7 +14,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.exceptions.code.CustomResponseCode; import org.runimo.runimo.hatch.exception.HatchHttpResponseCode; import org.springframework.beans.factory.annotation.Autowired; @@ -29,19 +30,18 @@ class HatchControllerTest { @LocalServerPort int port; - - @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private CleanUpUtil cleanUpUtil; - + @Autowired + private TokenUtils tokenUtils; + private String token; @Autowired private ObjectMapper objectMapper; @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -52,7 +52,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/hatch_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자의_알_부화_성공_8회() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); for (int i = 0; i < 8; i++) { int incubationEggId = i + 3; @@ -79,7 +78,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/hatch_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자의_알_부화_실패_부화가능한_상태가_아님() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); CustomResponseCode responseCode = HatchHttpResponseCode.HATCH_EGG_NOT_READY; given() @@ -100,7 +98,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/hatch_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자의_알_부화_실패_알_존재하지_않음() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); CustomResponseCode responseCode = HatchHttpResponseCode.HATCH_EGG_NOT_FOUND; given() diff --git a/src/test/java/org/runimo/runimo/records/api/RecordAcceptanceTest.java b/src/test/java/org/runimo/runimo/records/api/RecordAcceptanceTest.java index 30ecf7a7..c9e497bd 100644 --- a/src/test/java/org/runimo/runimo/records/api/RecordAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/records/api/RecordAcceptanceTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.records.controller.request.RecordSaveRequest; import org.runimo.runimo.records.controller.request.RecordUpdateRequest; import org.runimo.runimo.records.service.usecases.dtos.SegmentPace; @@ -32,19 +32,22 @@ class RecordAcceptanceTest { private static final String USER_UUID = "test-user-uuid-1"; - private static final String AUTH_HEADER_PREFIX = "Bearer "; @LocalServerPort int port; @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private ObjectMapper objectMapper; @Autowired private CleanUpUtil cleanUpUtil; + @Autowired + private TokenUtils tokenUtils; + + private String token; + @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(USER_UUID); } @AfterEach @@ -56,8 +59,6 @@ void tearDown() { @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 달리기_기록_저장_성공_기록_id_반환() throws Exception { // given - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - // 구간별 페이스 데이터 List segmentPaces = List.of( new SegmentPace(1.0, 732000), @@ -93,8 +94,6 @@ void tearDown() { @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 달리기_기록_조회_성공_구간별_페이스_포함() throws Exception { // given - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - // 선행 조건: 달리기 기록 저장 List segmentPaces = List.of( new SegmentPace(1.0, 732000), @@ -146,8 +145,6 @@ void tearDown() { @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 주간_달리기_거리_조회_성공시_정확한_정보를_반환한다() { // given - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); - // when & then given() .header("Authorization", token) @@ -181,8 +178,6 @@ void tearDown() { @Sql(scripts = "/sql/weekly_record_partial_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 주간_달리기_거리_조회_성공시_일부_날짜에_데이터가_없을때_0을_반환한다() { // given - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); - // when & then given() .header("Authorization", token) @@ -216,9 +211,6 @@ void tearDown() { @WithMockUser(username = USER_UUID) @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 월간_기록_통계_조회_성공시_정확한_정보를_반환한다() { - // given - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); - // when & then given() .header("Authorization", token) @@ -247,9 +239,6 @@ void tearDown() { @WithMockUser(username = USER_UUID) @Sql(scripts = "/sql/weekly_record_partial_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 월간_기록_통계_조회_잘못된_요청_데이터() { - // given - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); - // when & then given() .header("Authorization", token) @@ -264,6 +253,7 @@ void tearDown() { } @Test + @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 월간_기록_통계_조회_인증_실패() { // when & then given() @@ -281,7 +271,6 @@ void tearDown() { @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자_기록_페이지네이션_조회() { - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); given() .contentType(ContentType.JSON) @@ -306,7 +295,6 @@ void tearDown() { @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자_기록_페이지네이션_조회_결과_없음() { - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); given() .contentType(ContentType.JSON) @@ -329,7 +317,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자_기록_페이지네이션_조회_잘못된_요청() { - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); given() .contentType(ContentType.JSON) @@ -346,7 +333,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/weekly_record_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자_기록_업데이트() throws JsonProcessingException { - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); RecordUpdateRequest request = new RecordUpdateRequest( "예시 제목", "오늘은 올림픽 공원을 달렸어요.", diff --git a/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java b/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java index 6639310d..ac814fb1 100644 --- a/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java @@ -16,7 +16,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.records.RecordFixtures; import org.runimo.runimo.records.controller.request.RecordSaveRequest; import org.runimo.runimo.rewards.controller.request.RewardClaimRequest; @@ -31,19 +31,22 @@ @ActiveProfiles("test") class RewardAcceptanceTest { + private static final String TEST_USER_UUID = "test-user-uuid-1"; private static final LocalDateTime pivotTime = LocalDateTime.of(2023, 10, 1, 10, 0); @LocalServerPort private int port; @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private CleanUpUtil cleanUpUtil; @Autowired private ObjectMapper objectMapper; + private String token; + @Autowired + private TokenUtils tokenUtils; @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach() @@ -55,10 +58,9 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 달리기_기록_저장_후_주간_첫번째_달리기보상_수령() throws JsonProcessingException { - String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); RecordSaveRequest request = RecordFixtures.createRecordSaveRequest(); ValidatableResponse res = given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -74,7 +76,7 @@ void tearDown() { RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(recordId); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() @@ -87,10 +89,9 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 달리기_보상_수령_후_재시도_시_예외() throws JsonProcessingException { - String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); RecordSaveRequest request = RecordFixtures.createRecordSaveRequest(); ValidatableResponse res = given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -106,7 +107,7 @@ void tearDown() { RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(recordId); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() @@ -117,7 +118,7 @@ void tearDown() { .body("payload", notNullValue()); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() @@ -130,8 +131,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 첫번째_기록이_이번주_첫번째_달리기가_아니라서_알_미지급() throws JsonProcessingException { - String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - // 첫번째 기록 저장 RecordSaveRequest firstRequest = new RecordSaveRequest( pivotTime, @@ -140,7 +139,7 @@ void tearDown() { 1000L, null); ValidatableResponse firstRes = given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(firstRequest)) .contentType(ContentType.JSON) .when() @@ -161,7 +160,7 @@ void tearDown() { 1000L, null); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(secondRequest)) .contentType(ContentType.JSON) .when() @@ -176,7 +175,7 @@ void tearDown() { RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(firstRecordId); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() @@ -192,11 +191,10 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 달리기_기록_저장_후_애정_포인트_지급() throws JsonProcessingException { - String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); RecordSaveRequest request = RecordFixtures.createRecordSaveRequest(); ValidatableResponse res = given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -212,7 +210,7 @@ void tearDown() { RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(recordId); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() @@ -227,7 +225,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 기준거리_미달이면_애정을_미지급() throws JsonProcessingException { - String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); RecordSaveRequest request = new RecordSaveRequest( pivotTime, pivotTime.plusMinutes(20), @@ -236,7 +233,7 @@ void tearDown() { List.of() ); ValidatableResponse res = given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -252,7 +249,7 @@ void tearDown() { RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(recordId); given() - .header("Authorization", header) + .header("Authorization", token) .body(objectMapper.writeValueAsString(rewardClaimRequest)) .contentType(ContentType.JSON) .when() diff --git a/src/test/java/org/runimo/runimo/runimo/controller/RunimoControllerTest.java b/src/test/java/org/runimo/runimo/runimo/controller/RunimoControllerTest.java index e94ae5be..33780f32 100644 --- a/src/test/java/org/runimo/runimo/runimo/controller/RunimoControllerTest.java +++ b/src/test/java/org/runimo/runimo/runimo/controller/RunimoControllerTest.java @@ -3,6 +3,7 @@ import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.RestAssured; @@ -11,7 +12,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.exceptions.code.CustomResponseCode; import org.runimo.runimo.runimo.exception.RunimoHttpResponseCode; import org.springframework.beans.factory.annotation.Autowired; @@ -28,11 +29,12 @@ class RunimoControllerTest { @LocalServerPort int port; - @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private CleanUpUtil cleanUpUtil; + @Autowired + private TokenUtils tokenUtils; + + private String token; @Autowired private ObjectMapper objectMapper; @@ -40,6 +42,7 @@ class RunimoControllerTest { @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -51,7 +54,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/get_my_runimo_list_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 보유_러니모_목록_조회_성공() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); given() .header("Authorization", token) @@ -79,7 +81,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/get_all_runimo_type_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 전체_러니모_종류_조회_성공() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); given() .header("Authorization", token) @@ -113,7 +114,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/set_main_runimo_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 대표_러니모_설정_성공() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); given() .header("Authorization", token) @@ -133,7 +133,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/set_main_runimo_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 대표_러니모_설정_실패_러니모의_소유자_아님() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); CustomResponseCode responseCode = RunimoHttpResponseCode.USER_DO_NOT_OWN_RUNIMO; given() @@ -154,7 +153,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/set_main_runimo_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 대표_러니모_설정_실패_러니모_존재하지않음() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); CustomResponseCode responseCode = RunimoHttpResponseCode.RUNIMO_NOT_FOUND; given() diff --git a/src/test/java/org/runimo/runimo/user/api/IncubatingEggAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/IncubatingEggAcceptanceTest.java index 87cfe784..a3235b69 100644 --- a/src/test/java/org/runimo/runimo/user/api/IncubatingEggAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/IncubatingEggAcceptanceTest.java @@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.notNullValue; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -13,7 +14,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.user.controller.request.RegisterEggRequest; import org.runimo.runimo.user.controller.request.UseLovePointRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -30,17 +31,19 @@ class IncubatingEggAcceptanceTest { @LocalServerPort int port; - @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private CleanUpUtil cleanUpUtil; @Autowired private ObjectMapper objectMapper; + @Autowired + private TokenUtils tokenUtils; + private String token; + @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -51,7 +54,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자의_부화중인_알_조회_성공() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); given() .header("Authorization", token) @@ -73,7 +75,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 사용자의_알을_부화중으로_변경() throws JsonProcessingException { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); RegisterEggRequest request = new RegisterEggRequest(1L); given() @@ -93,7 +94,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 부화중인_알에_애정을_부여() throws JsonProcessingException { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); Long incubatingEggId = 1L; UseLovePointRequest request = new UseLovePointRequest(20L); given() @@ -115,8 +115,6 @@ void tearDown() { @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 알에_애정을_부여하면_사용자의_보유_애정이_감소한다() throws JsonProcessingException { // given - String userUuid = "test-user-uuid-1"; - String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid); Long incubatingEggId = 1L; // 사용자의 초기 애정 포인트 조회 @@ -157,7 +155,8 @@ void tearDown() { .then() .log().all() .statusCode(200) - .body("payload.user_info.love_point", equalTo(initialLovePoint - useLovePointAmount.intValue())); + .body("payload.user_info.love_point", + equalTo(initialLovePoint - useLovePointAmount.intValue())); } @@ -165,8 +164,6 @@ void tearDown() { @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 보유한_애정보다_더_많은_애정부여_요청_시_예외() throws JsonProcessingException { // given - String userUuid = "test-user-uuid-1"; - String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid); Long incubatingEggId = 1L; // 사용자의 초기 애정 포인트 조회 @@ -201,8 +198,6 @@ void tearDown() { @Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 애정부여_예외_시_애정보유량_유지() throws JsonProcessingException { // given - String userUuid = "test-user-uuid-1"; - String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid); Long incubatingEggId = 1L; // 사용자의 초기 애정 포인트 조회 @@ -248,25 +243,22 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 알_등록_후_조회() throws JsonProcessingException { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - Integer eggId = given() - .header("Authorization", token) - .contentType(ContentType.JSON) + .header("Authorization", token) + .contentType(ContentType.JSON) - .when() - .get("/api/v1/users/eggs") - - .then() - .log().ifError() - .statusCode(200) - .body("payload.items", notNullValue()) - .extract() - .path("payload.items[0].item_id"); + .when() + .get("/api/v1/users/eggs") + .then() + .log().ifError() + .statusCode(200) + .body("payload.items", notNullValue()) + .extract() + .path("payload.items[0].item_id"); - RegisterEggRequest request = new RegisterEggRequest((long)eggId); + RegisterEggRequest request = new RegisterEggRequest((long) eggId); given() .header("Authorization", token) @@ -295,6 +287,5 @@ void tearDown() { .body("payload.incubating_eggs[0].name", notNullValue()); - } } diff --git a/src/test/java/org/runimo/runimo/user/api/MainViewAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/MainViewAcceptanceTest.java index d7e9426e..ffb51cd8 100644 --- a/src/test/java/org/runimo/runimo/user/api/MainViewAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/MainViewAcceptanceTest.java @@ -2,6 +2,7 @@ import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import io.restassured.RestAssured; import io.restassured.http.ContentType; @@ -9,7 +10,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -20,18 +21,19 @@ @ActiveProfiles("test") class MainViewAcceptanceTest { - private static final String USER_UUID = "test-user-uuid-1"; - private static final String AUTH_HEADER_PREFIX = "Bearer "; @LocalServerPort int port; @Autowired - private JwtTokenFactory jwtTokenFactory; - @Autowired private CleanUpUtil cleanUpUtil; + @Autowired + private TokenUtils tokenUtils; + private String token; + @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -42,9 +44,6 @@ void tearDown() { @Test @Sql(scripts = "/sql/main_view_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 메인화면_조회_성공시_정확한_정보를_반환한다() { - // given - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken(USER_UUID); - // when & then given() .header("Authorization", token) @@ -66,8 +65,8 @@ void tearDown() { @Test @Sql(scripts = "/sql/main_view_data.sql") void 메인화면_조회시_대표_러니모가_없으면_null_로반환() { - String token = AUTH_HEADER_PREFIX + jwtTokenFactory.generateAccessToken("test-user-uuid-2"); // when & then + String token = tokenUtils.createTokenByUserPublicId("test-user-uuid-2"); given() .header("Authorization", token) .contentType(ContentType.JSON) diff --git a/src/test/java/org/runimo/runimo/user/api/MyPageAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/MyPageAcceptanceTest.java index 646760d3..c6bfc378 100644 --- a/src/test/java/org/runimo/runimo/user/api/MyPageAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/MyPageAcceptanceTest.java @@ -2,6 +2,7 @@ import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import io.restassured.RestAssured; import io.restassured.http.ContentType; @@ -11,7 +12,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -27,12 +28,15 @@ class MyPageAcceptanceTest { private Integer port; @Autowired private CleanUpUtil cleanUpUtil; + @Autowired - private JwtTokenFactory jwtTokenFactory; + private TokenUtils tokenUtils; + private String token; @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -45,11 +49,10 @@ void tearDown() { @Sql(scripts = "/sql/user_mypage_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 마이페이지_조회_시_프로필정보와_최근_달리기가_표시된다() { - String accessToken = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); int diff = (int) LocalDateTime.parse("2025-03-29T13:00:00") .until(LocalDateTime.now(), ChronoUnit.DAYS); given() - .header("Authorization", accessToken) + .header("Authorization", token) .contentType(ContentType.JSON) .when() .get("/api/v1/users/me") diff --git a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java index a3fa5675..4aed0e56 100644 --- a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java @@ -9,6 +9,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -20,6 +21,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.auth.controller.request.AuthSignupRequest; import org.runimo.runimo.auth.jwt.JwtTokenFactory; import org.runimo.runimo.auth.service.SignUpUsecase; @@ -36,8 +38,8 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.jdbc.Sql; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class UserItemAcceptanceTest { @LocalServerPort @@ -51,13 +53,16 @@ class UserItemAcceptanceTest { @MockitoBean private SignUpUsecase signUpUsecaseImpl; - + @Autowired + private TokenUtils tokenUtils; + private String token; @Autowired private CleanUpUtil cleanUpUtil; @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach() @@ -69,11 +74,9 @@ void tearDown() { @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 아이템_조회_성공() { // given - String jwt = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - // when + then given() - .header("Authorization", jwt) + .header("Authorization", token) .when() .get("/api/v1/users/eggs") .then() @@ -90,12 +93,11 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 아이템_사용시_보유량감소() throws JsonProcessingException { - String jwt = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); UseItemRequest request = new UseItemRequest(1L, 2L); given() - .header("Authorization", jwt) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -105,7 +107,7 @@ void tearDown() { .statusCode(HttpStatus.OK.value()); given() - .header("Authorization", jwt) + .header("Authorization", token) .when() .get("/api/v1/users/eggs") .then() @@ -119,11 +121,10 @@ void tearDown() { @Test @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 보유한_수량보다_더_많은_요청_시_에러() throws JsonProcessingException { - String jwt = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); UseItemRequest request = new UseItemRequest(1L, 10L); given() - .header("Authorization", jwt) + .header("Authorization", token) .body(objectMapper.writeValueAsString(request)) .contentType(ContentType.JSON) .when() @@ -138,7 +139,6 @@ void tearDown() { void 카카오_회원가입후_알_지급_성공() throws JsonProcessingException { String registerToken = jwtTokenFactory.generateSignupTemporalToken("test-pid", SocialProvider.KAKAO, UUID.randomUUID().toString()); - String token = jwtTokenFactory.generateAccessToken("test-user-uuid-1"); when(signUpUsecaseImpl.register(any())) .thenReturn(new SignupUserResponse( 1L, @@ -166,7 +166,7 @@ void tearDown() { .getString("payload.token_pair.access_token"); given() - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", accessToken) .when() .get("/api/v1/users/eggs") .then() diff --git a/src/test/java/org/runimo/runimo/user/api/UserWithdrawAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/UserWithdrawAcceptanceTest.java index ba6399d6..6361f108 100644 --- a/src/test/java/org/runimo/runimo/user/api/UserWithdrawAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/UserWithdrawAcceptanceTest.java @@ -1,6 +1,7 @@ package org.runimo.runimo.user.api; import static io.restassured.RestAssured.given; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import io.restassured.RestAssured; import io.restassured.http.ContentType; @@ -8,7 +9,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.runimo.runimo.CleanUpUtil; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -24,14 +25,17 @@ class UserWithdrawAcceptanceTest { int port; @Autowired - private JwtTokenFactory jwtTokenFactory; + private CleanUpUtil cleanUpUtil; + @Autowired - private CleanUpUtil cleanUpUtil; + private TokenUtils tokenUtils; + private String token; @BeforeEach void setUp() { RestAssured.port = port; + token = tokenUtils.createTokenByUserPublicId(TEST_USER_UUID); } @AfterEach @@ -44,8 +48,6 @@ void tearDown() { @Sql(scripts = "/sql/user_mypage_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 회원_탈퇴_성공_시_유저_조회_불가() { - String token = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - given() .header("Authorization", token) .when() diff --git a/src/test/java/org/runimo/runimo/user/controller/MainViewControllerTest.java b/src/test/java/org/runimo/runimo/user/controller/MainViewControllerTest.java index c63380a1..bf295026 100644 --- a/src/test/java/org/runimo/runimo/user/controller/MainViewControllerTest.java +++ b/src/test/java/org/runimo/runimo/user/controller/MainViewControllerTest.java @@ -2,19 +2,21 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.configs.ControllerTest; import org.runimo.runimo.runimo.service.dto.MainRunimoStat; import org.runimo.runimo.user.UserFixtures; import org.runimo.runimo.user.service.UserFinder; -import org.runimo.runimo.user.service.dto.response.MainViewResponse; import org.runimo.runimo.user.service.dto.UserMainViewInfo; +import org.runimo.runimo.user.service.dto.response.MainViewResponse; import org.runimo.runimo.user.service.usecases.query.MainViewQueryUsecase; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -32,15 +34,17 @@ class MainViewControllerTest { private UserFinder userFinder; @MockitoBean private MainViewQueryUsecase mainViewUsecase; - @Autowired - private JwtTokenFactory jwtTokenFactory; + + private String token; + + @BeforeEach + void setUp() { + token = TokenUtils.createTestOnlyToken(TEST_USER_UUID); + } @Test void 메인_화면_조회_성공() throws Exception { // given - - String accessToken = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); - MainViewResponse response = new MainViewResponse( new MainRunimoStat( "example", @@ -58,7 +62,7 @@ class MainViewControllerTest { Optional.ofNullable(UserFixtures.getDefaultUser())); // when & then mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/main") - .header("Authorization", accessToken) + .header("Authorization", token) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) @@ -66,8 +70,11 @@ class MainViewControllerTest { .andExpect(jsonPath("$.payload.main_runimo_stat_nullable.name").value("example")) .andExpect(jsonPath("$.payload.main_runimo_stat_nullable.image_url").value( "https://example.com/images/user1.png")) - .andExpect(jsonPath("$.payload.main_runimo_stat_nullable.total_running_count").value(100)) - .andExpect(jsonPath("$.payload.main_runimo_stat_nullable.total_distance_in_meters").value(3000)) + .andExpect( + jsonPath("$.payload.main_runimo_stat_nullable.total_running_count").value(100)) + .andExpect( + jsonPath("$.payload.main_runimo_stat_nullable.total_distance_in_meters").value( + 3000)) .andExpect(jsonPath("$.payload.user_info.love_point").value(2)) .andExpect(jsonPath("$.payload.user_info.total_egg_count").value(3)); } diff --git a/src/test/java/org/runimo/runimo/user/controller/MyPageControllerTest.java b/src/test/java/org/runimo/runimo/user/controller/MyPageControllerTest.java index 25d4b9b4..6918b509 100644 --- a/src/test/java/org/runimo/runimo/user/controller/MyPageControllerTest.java +++ b/src/test/java/org/runimo/runimo/user/controller/MyPageControllerTest.java @@ -10,9 +10,11 @@ import java.time.LocalDateTime; import java.util.NoSuchElementException; import javax.naming.NoPermissionException; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.auth.jwt.JwtResolver; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.auth.jwt.UserDetail; import org.runimo.runimo.configs.ControllerTest; import org.runimo.runimo.user.service.dto.LatestRunningRecord; import org.runimo.runimo.user.service.dto.response.MyPageViewResponse; @@ -28,10 +30,9 @@ @ControllerTest(controllers = {MyPageController.class}) class MyPageControllerTest { + private static final String TEST_USER_UUID = "test-user-uuid-1"; @Autowired private MockMvc mockMvc; - @Autowired - private JwtTokenFactory jwtTokenFactory; @MockitoBean private MyPageQueryUsecase myPageQueryUsecase; @MockitoBean @@ -39,12 +40,17 @@ class MyPageControllerTest { @MockitoBean private UserIdResolver userIdResolver; + private String token; + + @BeforeEach + void setUp() { + token = TokenUtils.createTestOnlyToken(TEST_USER_UUID); + } @Test @WithMockUser(username = "test-user-uuid-1") void 마이_페이지_조회_성공() throws Exception { // given - String accessToken = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); MyPageViewResponse response = new MyPageViewResponse( "Daniel", @@ -62,14 +68,14 @@ class MyPageControllerTest { when(myPageQueryUsecase.execute(any())) .thenReturn(response); - when(jwtResolver.getUserIdFromJwtToken(any())) - .thenReturn("test-user-uuid-1"); + when(jwtResolver.getUserDetailFromJwtToken(any())) + .thenReturn(new UserDetail("test-user-uuid-1", "USER")); when(userIdResolver.resolveArgument(any(), any(), any(), any())) .thenReturn(1L); // when & then mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/users/me") - .header("Authorization", accessToken) + .header("Authorization", token) .contentType(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) @@ -108,10 +114,12 @@ class MyPageControllerTest { @WithMockUser(username = "test-user-uuid-3") void 마이_페이지_조회_실패_사용자정보_없음() throws Exception { // given - String accessToken = "Bearer " + jwtTokenFactory.generateAccessToken("non-existent-user"); + String accessToken = TokenUtils.createTestOnlyToken("non-existing-user-uuid"); when(myPageQueryUsecase.execute(any())) .thenThrow(new NoSuchElementException("User not found")); + when(jwtResolver.getUserDetailFromJwtToken(any())) + .thenReturn(new UserDetail("non-existing-user-uuid", "USER")); // when & then mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/users/me") diff --git a/src/test/java/org/runimo/runimo/user/controller/QueryItemControllerTest.java b/src/test/java/org/runimo/runimo/user/controller/QueryItemControllerTest.java index 17a00819..5cbbf324 100644 --- a/src/test/java/org/runimo/runimo/user/controller/QueryItemControllerTest.java +++ b/src/test/java/org/runimo/runimo/user/controller/QueryItemControllerTest.java @@ -2,14 +2,16 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.runimo.runimo.TestConsts.TEST_USER_UUID; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.ArrayList; import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.runimo.runimo.auth.jwt.JwtTokenFactory; +import org.runimo.runimo.TokenUtils; import org.runimo.runimo.configs.ControllerTest; import org.runimo.runimo.user.UserFixtures; import org.runimo.runimo.user.service.UserFinder; @@ -26,8 +28,6 @@ class QueryItemControllerTest { @Autowired private MockMvc mockMvc; - @Autowired - private JwtTokenFactory jwtTokenFactory; @MockitoBean private UserFinder userFinder; @MockitoBean @@ -35,15 +35,21 @@ class QueryItemControllerTest { @MockitoBean private UseItemUsecase useItemUsecase; + private String token; + + @BeforeEach + void setUp() { + token = TokenUtils.createTestOnlyToken(TEST_USER_UUID); + } + @Test void 보유한_아이템_조회_성공() throws Exception { - String accessToken = jwtTokenFactory.generateAccessToken("test-user-uuid-1"); given(myItemQueryUsecase.queryMyAllItems(any())) .willReturn(new ItemQueryResponse(new ArrayList<>())); given(userFinder.findUserByPublicId(any())) .willReturn(Optional.of(UserFixtures.getDefaultUser())); mockMvc.perform(get("/api/v1/users/me/items") - .header("Authorization", "Bearer " + accessToken) + .header("Authorization", token) .param("itemType", "EGG")) .andDo(print()) .andExpect(status().isOk()); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 294dae77..a962a515 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -15,6 +15,8 @@ runimo: path: ${SWAGGER_UI_SERVER:http://localhost:8080} spring: + profiles: + active: test config: import: - optional:file:${ENV_PATH:.}/.env.${SPRING_PROFILES_ACTIVE:test}[.properties] diff --git a/src/test/resources/sql/schema.sql b/src/test/resources/sql/schema.sql index d84e05c1..dc2e3a27 100644 --- a/src/test/resources/sql/schema.sql +++ b/src/test/resources/sql/schema.sql @@ -29,6 +29,7 @@ CREATE TABLE `users` `total_time_in_seconds` BIGINT NOT NULL DEFAULT 0, `main_runimo_id` BIGINT, `gender` VARCHAR(24), + `role` VARCHAR(24) NOT NULL DEFAULT 'USER', `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -91,16 +92,16 @@ CREATE TABLE `signup_token` CREATE TABLE `running_record` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, `record_public_id` VARCHAR(255) NOT NULL, `title` VARCHAR(255), `description` VARCHAR(255), `img_url` VARCHAR(255), `started_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `end_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - `total_distance` INTEGER, - `pace_in_milli_seconds` INTEGER, + `total_distance` BIGINT, + `pace_in_milli_seconds` BIGINT, `is_rewarded` BOOLEAN, `pace_per_km` VARCHAR(10000), `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -110,7 +111,7 @@ CREATE TABLE `running_record` CREATE TABLE `item` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `item_code` VARCHAR(255) NOT NULL, `description` VARCHAR(255), @@ -126,7 +127,7 @@ CREATE TABLE `item` CREATE TABLE `egg_type` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(64) NOT NULL, `code` VARCHAR(64) NOT NULL, `required_distance_in_meters` BIGINT, @@ -139,11 +140,11 @@ CREATE TABLE `egg_type` CREATE TABLE `item_activity` ( - `id` INTEGER PRIMARY KEY AUTO_INCREMENT, - `activity_user_id` INTEGER NOT NULL, - `activity_item_id` INTEGER NOT NULL, + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `activity_user_id` BIGINT NOT NULL, + `activity_item_id` BIGINT NOT NULL, `activity_event_type` VARCHAR(255) NOT NULL, - `quantity` INTEGER, + `quantity` BIGINT, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -152,9 +153,9 @@ CREATE TABLE `item_activity` CREATE TABLE `user_item` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, - `item_id` INTEGER NOT NULL, - `quantity` INTEGER NOT NULL, + `user_id` BIGINT NOT NULL, + `item_id` BIGINT NOT NULL, + `quantity` BIGINT NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted_at` TIMESTAMP NULL @@ -163,10 +164,10 @@ CREATE TABLE `user_item` CREATE TABLE `incubating_egg` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, - `user_id` INTEGER NOT NULL, - `egg_id` INTEGER NOT NULL, - `current_love_point_amount` INTEGER, - `hatch_require_amount` INTEGER, + `user_id` BIGINT NOT NULL, + `egg_id` BIGINT NOT NULL, + `current_love_point_amount` BIGINT, + `hatch_require_amount` BIGINT, `egg_status` VARCHAR(255), `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, @@ -223,9 +224,9 @@ VALUES (1, '마당', 'A100', 0, 1, NOW(), NOW()), INSERT INTO runimo_definition (id, name, code, description, img_url, egg_type_id, created_at, updated_at) VALUES (1, '강아지', 'R-101', '마당-강아지예여', 'http://dummy1', 1, NOW(), NOW()), - (2, '고양이', 'R-102', '마당-고양이예여', 'http://dummy2', 1, NOW(), NOW()), - (3, '토끼', 'R-103', '마당-토끼예여', 'http://dummy2', 1, NOW(), NOW()), - (4, '오리', 'R-104', '마당-오리예여', 'http://dummy2', 1, NOW(), NOW()), + (2, '고양이', 'R-102', '마당-고양이예여', 'http://dummy1', 1, NOW(), NOW()), + (3, '토끼', 'R-103', '마당-토끼예여', 'http://dummy1', 1, NOW(), NOW()), + (4, '오리', 'R-104', '마당-오리예여', 'http://dummy1', 1, NOW(), NOW()), (5, '늑대 강아지', 'R-105', '늑대 강아지예여', 'http://dummy2', 2, NOW(), NOW()), (6, '숲 고양이', 'R-106', '숲 고양이예여', 'http://dummy2', 2, NOW(), NOW()), (7, '나뭇잎 토끼', 'R-107', '나뭇잎 토끼예여', 'http://dummy2', 2, NOW(), NOW()),