From 453f04d20739bfdbb24f192d87329adc6918e573 Mon Sep 17 00:00:00 2001 From: Eric-HAN-01 Date: Mon, 23 Jun 2025 11:22:07 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20=EB=AA=A8=EB=93=A0=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/AdminController.java | 1 - .../chatbot/service/ChatBotReviewService.java | 3 -- .../ufit/domain/user/service/UserService.java | 1 - .../java/com/ureca/ufit/entity/RatePlan.java | 6 ++-- .../ufit/global/auth/filter/JwtFilter.java | 7 ----- .../ufit/global/auth/filter/LoginFilter.java | 1 - .../handler/CustomLoginSuccessHandler.java | 6 ---- .../auth/handler/CustomLogoutHandler.java | 11 +++---- .../global/auth/provider/LoginProvider.java | 2 -- .../ufit/global/auth/service/AuthService.java | 7 ----- .../ureca/ufit/global/auth/util/JwtUtil.java | 6 ++-- .../ufit/global/config/SecurityConfig.java | 9 ++---- .../global/exception/ErrorResponseDto.java | 3 -- .../exception/GlobalExceptionHandler.java | 3 -- .../global/profanity/BanwordFilterPolicy.java | 6 ++-- .../global/profanity/ProfanityFilter.java | 5 +--- .../admin/controller/AdminControllerTest.java | 5 ++-- .../ufit/admin/service/AdminServiceTest.java | 8 ----- .../controller/ChatBotControllerTest.java | 5 ---- .../ChatBotMessageRepositoryTest.java | 5 ---- .../ChatBotReviewRepositoryTest.java | 6 ---- .../chatbot/service/ChatRoomServiceTest.java | 9 ------ .../global/profanity/ProfanityFilterTest.java | 12 -------- .../RatePlanQueryRepositoryTest.java | 30 ------------------- .../user/controller/UserControllerTest.java | 20 ------------- .../ureca/ufit/user/filter/JwtFilterTest.java | 12 +------- .../ufit/user/filter/LoginFilterTest.java | 3 -- .../ufit/user/provider/LoginProviderTest.java | 3 -- .../ufit/user/service/AuthServiceTest.java | 3 -- .../ufit/user/service/UserServiceTest.java | 3 -- 30 files changed, 19 insertions(+), 182 deletions(-) diff --git a/src/main/java/com/ureca/ufit/domain/admin/controller/AdminController.java b/src/main/java/com/ureca/ufit/domain/admin/controller/AdminController.java index 28acfa0..9a9840a 100644 --- a/src/main/java/com/ureca/ufit/domain/admin/controller/AdminController.java +++ b/src/main/java/com/ureca/ufit/domain/admin/controller/AdminController.java @@ -44,7 +44,6 @@ public ResponseEntity deleteRatePlan(String ratePlanId) return ResponseEntity.ok(response); } - // 요금제 지표 조회 @GetMapping("/api/admin/rateplans/metrics") public ResponseEntity getRatePlanMetrics( @RequestParam(defaultValue = "1") int page, diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java index 4290da0..86a9ea5 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java @@ -73,9 +73,6 @@ private QuestionSummaryDto requestUserQuerySummary(CreateChatBotReviewRequest re CreateUserQuerySummaryRequest chatReviewSummaryRequest = new CreateUserQuerySummaryRequest( request.recommendationMessageId()); - - // QuestionSummaryDto questionSummaryDto = restTemplate.postForObject(url, chatReviewSummaryRequest, - // QuestionSummaryDto.class); RestClient restClient = RestClient.create(); QuestionSummaryDto questionSummaryDto = restClient.post() diff --git a/src/main/java/com/ureca/ufit/domain/user/service/UserService.java b/src/main/java/com/ureca/ufit/domain/user/service/UserService.java index 9a74c1f..48b49ad 100644 --- a/src/main/java/com/ureca/ufit/domain/user/service/UserService.java +++ b/src/main/java/com/ureca/ufit/domain/user/service/UserService.java @@ -18,7 +18,6 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; - //DB 확인용 회원가입 @Transactional public RegisterResponse register(RegisterRequest request) { String encodedPassword = passwordEncoder.encode(request.password()); diff --git a/src/main/java/com/ureca/ufit/entity/RatePlan.java b/src/main/java/com/ureca/ufit/entity/RatePlan.java index 2c01fc6..81be657 100644 --- a/src/main/java/com/ureca/ufit/entity/RatePlan.java +++ b/src/main/java/com/ureca/ufit/entity/RatePlan.java @@ -118,9 +118,9 @@ public static RatePlan of(String planName, String summary, int monthlyFee, int d .dataAllowance(dataAllowance) .voiceAllowance(voiceAllowance) .smsAllowance(smsAllowance) - .basicBenefit(basicBenefit) // not null - .specialBenefit(specialBenefit) // null 가능 - .discountBenefit(discountBenefit) // null 가능.. + .basicBenefit(basicBenefit) + .specialBenefit(specialBenefit) + .discountBenefit(discountBenefit) .isEnabled(true) .isDeleted(false) .build(); diff --git a/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java b/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java index b44560f..1ef52e0 100644 --- a/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java +++ b/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java @@ -32,7 +32,6 @@ @RequiredArgsConstructor public class JwtFilter extends OncePerRequestFilter { - // 비회원 회원 모두 JWT검증 필요X private static final List WHITE_LIST = List.of( "/error", "/favicon.ico", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html", "/api/auth/login", @@ -46,7 +45,6 @@ public class JwtFilter extends OncePerRequestFilter { "/actuator/info" ); - // 비회원이면 JWT검증 필요X, 회원이면 JWT검증 필요 private static final List PUBLIC_LIST = List.of( "/api/chats/message", "/api/chats/review", @@ -66,10 +64,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse boolean isPublic = PUBLIC_LIST.stream().anyMatch(pub -> matcher.match(pub, request.getRequestURI())); - // 어세스 토큰 유효성 검사 시작 String bearerToken = request.getHeader(AUTH_HEADER); - // 비회원일 때 검증 로직 if (Optional.ofNullable(bearerToken).isEmpty()) { if (!isPublic) { throw new RestApiException(CommonErrorCode.NOT_EXIST_BEARER_SUFFIX); @@ -78,19 +74,16 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse return; } - // 어세스 토큰 추출 String accessToken = Optional.of(bearerToken) .filter(token -> token.startsWith(BEARER_PREFIX)) .map(token -> token.substring(BEARER_PREFIX.length())) .orElseThrow(() -> new RestApiException(CommonErrorCode.NOT_EXIST_BEARER_SUFFIX)); - // 어세스 토큰 검증, 블랙 리스트 확인 JwtUtil.validateAccessToken(accessToken, secretKey); if (Boolean.TRUE.equals(redisTemplate.hasKey(BLACKLIST_PREFIX + accessToken))) { throw new RestApiException(CommonErrorCode.INVALID_TOKEN); } - // 인증 객체를 설정하고 시큐리티 홀더에 저장 String email = JwtUtil.getEmail(accessToken, secretKey); UserDetails userDetails = userDetailsService.loadUserByUsername(email); Authentication authentication = new UsernamePasswordAuthenticationToken( diff --git a/src/main/java/com/ureca/ufit/global/auth/filter/LoginFilter.java b/src/main/java/com/ureca/ufit/global/auth/filter/LoginFilter.java index 1157e2d..e050147 100644 --- a/src/main/java/com/ureca/ufit/global/auth/filter/LoginFilter.java +++ b/src/main/java/com/ureca/ufit/global/auth/filter/LoginFilter.java @@ -33,7 +33,6 @@ public Authentication attemptAuthentication(HttpServletRequest request, Authentication authentication = new UsernamePasswordAuthenticationToken(email, password); - // 인증 메니저에게 인증 객체 위임 return this.getAuthenticationManager().authenticate(authentication); } } diff --git a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLoginSuccessHandler.java b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLoginSuccessHandler.java index 58c361d..49ade36 100644 --- a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLoginSuccessHandler.java +++ b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLoginSuccessHandler.java @@ -33,24 +33,18 @@ public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler { public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - // 로그인 성공 시 인증 객체의 principal을 정의하기 위한 유저 정보 CustomUserDetails userDetails = (CustomUserDetails)authentication.getPrincipal(); - // 로그인 성공 시 어세스/리프레시 토큰 발급 String accessToken = JwtUtil.createAccessToken(userDetails.email(), secretKeyKey); String refreshToken = JwtUtil.createRefreshToken(userDetails.email(), secretKeyKey); - // 레디스에 리프레시 토큰 저장 RefreshToken refreshTokenEntity = RefreshToken.of(refreshToken, userDetails.email()); refreshTokenRepository.save(refreshTokenEntity); - // 쿠키에 리프레시 토큰 저장 (timeout 3일) JwtUtil.updateRefreshTokenCookie(response, refreshToken, REFRESH_TOKEN_EXPIRED_MS / 1000); - // 헤더에 어세스 토큰 저장 response.setHeader(AUTH_HEADER, BEARER_PREFIX + accessToken); - // 바디에 Login Response 저장 LoginResponse loginResponse = LoginResponse.of(userDetails.getUsername(), userDetails.role()); objectMapper.writeValue(response.getWriter(), loginResponse); } diff --git a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java index 39afeca..29fef6f 100644 --- a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java +++ b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java @@ -36,7 +36,6 @@ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { try { - // 로그아웃 시 헤더에 있는 어세스 토큰 검증 String bearerToken = request.getHeader(AUTH_HEADER); if (bearerToken == null || !bearerToken.startsWith(BEARER_PREFIX)) { throw new RestApiException(CommonErrorCode.NOT_EXIST_BEARER_SUFFIX); @@ -46,19 +45,17 @@ public void logout(HttpServletRequest request, HttpServletResponse response, try { JwtUtil.validateAccessToken(accessToken, secretKey); - // 블랙 리스트에 어세스 토큰 추가 addToBlacklistRedis(accessToken); } catch (RestApiException e) { - // 어세스토큰 만료는 정상 처리 if( !e.getErrorCode().equals(CommonErrorCode.EXPIRED_TOKEN)) throw e; } String refreshToken = JwtUtil.getRefreshTokenCookies(request); - // 쿠키에서 리프레시 토큰 삭제 (timeout을 0으로 두어 즉시 삭제) + JwtUtil.updateRefreshTokenCookie(response, null, 0); - // Redis에서 해당 리프레시 토큰 키 삭제 + refreshTokenRepository.delete( refreshTokenRepository.findById(refreshToken).orElseThrow( () -> new RestApiException(CommonErrorCode.REFRESH_NOT_FOUND) @@ -66,7 +63,7 @@ public void logout(HttpServletRequest request, HttpServletResponse response, ); } catch (RestApiException e) { - // 쿠키나 레디스에서 리프레시 토큰을 찾지 못했을 경우 정상처리 + if(e.getErrorCode().equals(CommonErrorCode.REFRESH_NOT_FOUND)) return; try { @@ -79,7 +76,7 @@ public void logout(HttpServletRequest request, HttpServletResponse response, private void addToBlacklistRedis(String accessToken) { Date expiration = JwtUtil.getExpiration(accessToken, secretKey); - long ttl = expiration.getTime() - System.currentTimeMillis(); // TTL: 남은 시간 - 현재 시간 + long ttl = expiration.getTime() - System.currentTimeMillis(); redisTemplate.opsForValue().set(BLACKLIST_PREFIX + accessToken, "logout", ttl, TimeUnit.MILLISECONDS); } } diff --git a/src/main/java/com/ureca/ufit/global/auth/provider/LoginProvider.java b/src/main/java/com/ureca/ufit/global/auth/provider/LoginProvider.java index abd39a5..f0017a8 100644 --- a/src/main/java/com/ureca/ufit/global/auth/provider/LoginProvider.java +++ b/src/main/java/com/ureca/ufit/global/auth/provider/LoginProvider.java @@ -27,10 +27,8 @@ public Authentication authenticate(Authentication authentication) String email = authentication.getName(); - // 인증 객체의 principal을 정의하기 위한 유저 정보 UserDetails userDetails = userDetailsService.loadUserByUsername(email); - // 비밀번호 검증 String password = authentication.getCredentials().toString(); if (!passwordEncoder.matches(password, userDetails.getPassword())) { throw new RestApiException(UserErrorCode.USER_PASSWORD_MISMATCH); diff --git a/src/main/java/com/ureca/ufit/global/auth/service/AuthService.java b/src/main/java/com/ureca/ufit/global/auth/service/AuthService.java index 5be72f4..1f2dad5 100644 --- a/src/main/java/com/ureca/ufit/global/auth/service/AuthService.java +++ b/src/main/java/com/ureca/ufit/global/auth/service/AuthService.java @@ -26,31 +26,24 @@ public class AuthService { public void reissueToken(String bearerToken, String refreshToken, HttpServletResponse response) { - // 어세스 토큰 추출 String accessToken = bearerToken.substring(BEARER_PREFIX.length()); - // 블랙 리스트에 어세스 토큰이 있는 지 확인 if (redisTemplate.hasKey(BLACKLIST_PREFIX + accessToken)) { throw new RestApiException(CommonErrorCode.INVALID_TOKEN); } - // 리프레시 토큰이 레디스에 있는지 확인 RefreshToken refreshTokenEntity = refreshTokenRepository.findById(refreshToken).orElseThrow(() -> new RestApiException(CommonErrorCode.REFRESH_NOT_FOUND) ); - // 어세스 토큰이 만료되 었는지 검증하고 이메일 추출 String email = JwtUtil.getEmailOnlyIfExpired(accessToken, secretKey); - // 어세스 토큰과 리프레시 토큰의 매핑 검증 if (!email.equals(refreshTokenEntity.getEmail())) { throw new RestApiException(CommonErrorCode.REFRESH_DENIED); } - // 리프레시 토큰 만료 여부 검증 JwtUtil.validateRefreshToken(refreshToken, secretKey); - // 리프레시 토큰 폐기 후 어세스 토큰과 리프레시 토큰 재발급 (RTR) String newRefreshToken = JwtUtil.createRefreshToken(email, secretKey); RefreshToken newRefreshTokenEntity = RefreshToken.of(newRefreshToken, email); refreshTokenRepository.deleteById(refreshToken); diff --git a/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java b/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java index 9d6e017..f039da7 100644 --- a/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java +++ b/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java @@ -42,8 +42,8 @@ public class JwtUtil { public static final String COOKIE_HEADER_NAME = "Set-Cookie"; public static final String COOKIE_SAME_SITE_STRATEGY = "Lax"; - public static final int ACCESS_TOKEN_EXPIRED_MS = 1000 * 60 * 30; // 30분 - public static final int REFRESH_TOKEN_EXPIRED_MS = 1000 * 60 * 60 * 24 * 3; // 3일 + public static final int ACCESS_TOKEN_EXPIRED_MS = 1000 * 60 * 30; + public static final int REFRESH_TOKEN_EXPIRED_MS = 1000 * 60 * 60 * 24 * 3; public static String createToken(String email, String type, SecretKey secretKey, long expiresIn) { return Jwts.builder() @@ -117,10 +117,8 @@ private static void validateToken(String token, SecretKey secretKey, String expe } } - // 토큰 검증 및 만료된 토큰에서 사용자의 이메일을 추출(주의: 토큰 재발급 로직에서만 사용할 것!) public static String getEmailOnlyIfExpired(String token, SecretKey secretKey) { try { - // 만료되지 않았다면 재발급 대상이 아님 → 예외 발생 parseClaims(token, secretKey); throw new RestApiException(CommonErrorCode.REFRESH_DENIED); } catch (RestApiException e) { diff --git a/src/main/java/com/ureca/ufit/global/config/SecurityConfig.java b/src/main/java/com/ureca/ufit/global/config/SecurityConfig.java index 9b494e5..f671ebb 100644 --- a/src/main/java/com/ureca/ufit/global/config/SecurityConfig.java +++ b/src/main/java/com/ureca/ufit/global/config/SecurityConfig.java @@ -34,12 +34,10 @@ public class SecurityConfig { private static final String[] USER_AUTH_LIST = { - // 인증이 필요한 API 패턴 "/api/chats/{chatroomId:\\d+}" }; private static final String[] ADMIN_AUTH_LIST = { - // 관리자 인증이 필요한 API 패턴 "/api/admin/rateplans", "/api/admin/rateplans/{rateplanId:\\d+}", "/api/admin/rateplans/metrics", @@ -82,9 +80,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http - .addFilterBefore(exceptionHandlerFilter, UsernamePasswordAuthenticationFilter.class) // ← 예외 핸들러 - .addFilterBefore(loginFilter(), UsernamePasswordAuthenticationFilter.class) // ← 로그인 필터 - .addFilterBefore(jwtFilter, BasicAuthenticationFilter.class); // ← JWT 필터 + .addFilterBefore(exceptionHandlerFilter, UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(loginFilter(), UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(jwtFilter, BasicAuthenticationFilter.class); http .authorizeHttpRequests(auth -> auth @@ -104,7 +102,6 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http.build(); } - // Spring Security cors Bean 등록 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); diff --git a/src/main/java/com/ureca/ufit/global/exception/ErrorResponseDto.java b/src/main/java/com/ureca/ufit/global/exception/ErrorResponseDto.java index c87b49e..3157fa6 100644 --- a/src/main/java/com/ureca/ufit/global/exception/ErrorResponseDto.java +++ b/src/main/java/com/ureca/ufit/global/exception/ErrorResponseDto.java @@ -21,9 +21,6 @@ public class ErrorResponseDto { @JsonInclude(JsonInclude.Include.NON_EMPTY) private final List errors; - /** - * @Valid를 사용했을 때 에러가 발생한 경우 어느 필드에서 에러가 발생했는지 응답을 위한 ValidationError를 내부 정적 클래스 - */ @Getter @Builder @RequiredArgsConstructor diff --git a/src/main/java/com/ureca/ufit/global/exception/GlobalExceptionHandler.java b/src/main/java/com/ureca/ufit/global/exception/GlobalExceptionHandler.java index efb9847..a09710a 100644 --- a/src/main/java/com/ureca/ufit/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/ureca/ufit/global/exception/GlobalExceptionHandler.java @@ -74,16 +74,13 @@ protected ResponseEntity handleMethodArgumentNotValid( @NonNull WebRequest request) { log.warn(ex.getMessage(), ex); - // 필드 오류 우선 확인 String errMessage; if (!ex.getBindingResult().getFieldErrors().isEmpty()) { errMessage = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage(); } - // 클래스 레벨(Global) 오류 확인 else if (!ex.getBindingResult().getGlobalErrors().isEmpty()) { errMessage = ex.getBindingResult().getGlobalErrors().get(0).getDefaultMessage(); } - // 기본 메시지 else { errMessage = "잘못된 요청입니다."; } diff --git a/src/main/java/com/ureca/ufit/global/profanity/BanwordFilterPolicy.java b/src/main/java/com/ureca/ufit/global/profanity/BanwordFilterPolicy.java index 64bdfc5..a930053 100644 --- a/src/main/java/com/ureca/ufit/global/profanity/BanwordFilterPolicy.java +++ b/src/main/java/com/ureca/ufit/global/profanity/BanwordFilterPolicy.java @@ -1,9 +1,9 @@ package com.ureca.ufit.global.profanity; public enum BanwordFilterPolicy { - NUMBERS("[\\p{N}]"), // 모든 숫자 - WHITESPACES("[\\s]"), // 공백 문자 - FOREIGN("[\\p{L}&&[^ㄱ-ㅎ가-힣ㅏ-ㅣa-zA-Z]]"); // 한글/영문 제외 문자 (특수문자) + NUMBERS("[\\p{N}]"), + WHITESPACES("[\\s]"), + FOREIGN("[\\p{L}&&[^ㄱ-ㅎ가-힣ㅏ-ㅣa-zA-Z]]"); private final String regex; diff --git a/src/main/java/com/ureca/ufit/global/profanity/ProfanityFilter.java b/src/main/java/com/ureca/ufit/global/profanity/ProfanityFilter.java index 05bda90..4ecfc4a 100644 --- a/src/main/java/com/ureca/ufit/global/profanity/ProfanityFilter.java +++ b/src/main/java/com/ureca/ufit/global/profanity/ProfanityFilter.java @@ -20,26 +20,23 @@ public ProfanityFilter(List bannedWords) { .build(); this.attackPatterns = List.of( - //SQL Injection + Pattern.compile("(?i)(\\bor\\b|\\band\\b)?\\s*['\"].*?['\"]\\s*(=|>|<|like)?\\s*['\"].*?['\"]"), Pattern.compile("(?i)(union(.*?)select)"), Pattern.compile("(?i)(drop|insert|delete|update|select|truncate|alter)\\s+\\w+"), Pattern.compile("(?i)(--)|(#)"), - // XSS Pattern.compile("(?i).*?"), Pattern.compile("(?i)(onerror|onload|alert|prompt|confirm)\\s*="), Pattern.compile("(?i)<.*?javascript:.*?>"), Pattern.compile("(?i).*?"), - // 기타 명령어 Pattern.compile("(?i)exec\\s+(xp_cmdshell|sp_)"), Pattern.compile("(?i)benchmark\\s*\\(.*?\\)"), Pattern.compile("(?i)sleep\\s*\\(\\s*[0-9]+\\s*\\)") ); } - // 정제된 데이터 반환 public String normalize(String input, Set policies) { if (input == null || policies.isEmpty()) { return input; diff --git a/src/test/java/com/ureca/ufit/admin/controller/AdminControllerTest.java b/src/test/java/com/ureca/ufit/admin/controller/AdminControllerTest.java index ee194ff..cdbc133 100644 --- a/src/test/java/com/ureca/ufit/admin/controller/AdminControllerTest.java +++ b/src/test/java/com/ureca/ufit/admin/controller/AdminControllerTest.java @@ -31,10 +31,9 @@ void tearDown() { @DisplayName("요금제의 판매 상태를 변경한다.") @Test void updateRatePlanSalesStatus() throws Exception { - // given + RatePlan savedRatePlan = ratePlanRepository.save(RatePlanFixture.ratePlan("판매 중인 요금제", true, false)); - // when // then mockMvc.perform(patch("/api/admin/rateplans/{ratePlanId}", savedRatePlan.getId()) .contentType(APPLICATION_JSON) .header("Authorization", accessTokenOfAdmin) @@ -47,7 +46,7 @@ void updateRatePlanSalesStatus() throws Exception { @DisplayName("상품의 ID값이 없으면 판매 상태를 변경할 수 없다.") @Test void throwValidationExceptionWhenRatePlanIdIsNull() throws Exception { - // when // then + mockMvc.perform(patch("/api/admin/rateplans/{ratePlanId}", " ") .contentType(APPLICATION_JSON) .header("Authorization", accessTokenOfAdmin) diff --git a/src/test/java/com/ureca/ufit/admin/service/AdminServiceTest.java b/src/test/java/com/ureca/ufit/admin/service/AdminServiceTest.java index 2490093..846a800 100644 --- a/src/test/java/com/ureca/ufit/admin/service/AdminServiceTest.java +++ b/src/test/java/com/ureca/ufit/admin/service/AdminServiceTest.java @@ -50,7 +50,6 @@ class AdminServiceTest { @DisplayName("삭제되지 않고 판매 중인 요금Î제를 판매 중지시킨다.") @Test void pauseSalesWhenRatePlanIsSellingAndNotDeleted() { - // given final String id = "dsanfono2n4ioh198h89n"; RatePlan ratePlan = RatePlanFixture.ratePlan("판매 요금제", true, false); ReflectionTestUtils.setField(ratePlan, "id", "dsanfono2n4ioh198h89n"); @@ -61,10 +60,8 @@ void pauseSalesWhenRatePlanIsSellingAndNotDeleted() { given(ratePlanRepository.getById(anyString())).willReturn(ratePlan); given(ratePlanRepository.save(any(RatePlan.class))).willReturn(savedRatePlan); - // when RatePlanStatusResponse response = adminService.updateRatePlanSalesStatus(id); - // then assertAll( () -> assertThat(response.isEnabled()).isFalse(), () -> assertThat(response.ratePlanId()).isEqualTo(id) @@ -74,14 +71,12 @@ void pauseSalesWhenRatePlanIsSellingAndNotDeleted() { @DisplayName("삭제된 요금제의 판매 여부를 변경하지 못한다.") @Test void throwExceptionWhenDeletedRatePlanUpdateSalesStatus() { - // given final String id = "dsanfono2n4ioh198h89n"; RatePlan ratePlan = RatePlanFixture.ratePlan("삭제된 요금제", true, true); ReflectionTestUtils.setField(ratePlan, "id", "dsanfono2n4ioh198h89n"); given(ratePlanRepository.getById(anyString())).willReturn(ratePlan); - // when // then assertThatThrownBy(() -> adminService.updateRatePlanSalesStatus(id)) .isInstanceOf(RestApiException.class) .hasMessage(RatePlanErrorCode.RATE_PLAN_ALREADY_DELETED.getMessage()); @@ -90,17 +85,14 @@ void throwExceptionWhenDeletedRatePlanUpdateSalesStatus() { @DisplayName("판매중지이며 가입자가 한 명도 없을 때 요금제를 삭제한다.") @Test void deleteRatePlan() throws JsonProcessingException { - // given RatePlan plan = RatePlanFixture.ratePlan("테스트플랜", false, false); ReflectionTestUtils.setField(plan, "id", PLAN_ID); given(ratePlanRepository.findById(PLAN_ID)).willReturn(Optional.of(plan)); given(userRepository.countByRatePlanId(PLAN_ID)).willReturn(0L); doNothing().when(restTemplate).delete(anyString()); - // when DeleteRatePlanResponse response = adminService.deleteRatePlan(PLAN_ID); - // then assertThat(response.message()) .isEqualTo("요금제가 성공적으로 삭제되었습니다."); assertThat(plan.isDeleted()).isTrue(); diff --git a/src/test/java/com/ureca/ufit/chatbot/controller/ChatBotControllerTest.java b/src/test/java/com/ureca/ufit/chatbot/controller/ChatBotControllerTest.java index 82e1486..a60f2c3 100644 --- a/src/test/java/com/ureca/ufit/chatbot/controller/ChatBotControllerTest.java +++ b/src/test/java/com/ureca/ufit/chatbot/controller/ChatBotControllerTest.java @@ -34,10 +34,8 @@ void teardown() { @DisplayName("이미 존재하는 채팅방이 있으면 ID만 반환한다.") @Test void returnExistingChatRoomId() throws Exception { - // given ChatRoom existingChatRoom = chatRoomRepository.save(ChatRoomFixture.chatRoom(2L, loginUser)); - // when // then mockMvc.perform(post("/api/chats/rooms") .header("Authorization", accessTokenOfUser) .contentType(APPLICATION_JSON)) @@ -49,7 +47,6 @@ void returnExistingChatRoomId() throws Exception { @DisplayName("비회원이 요청하면 새로운 익명 채팅방을 생성한다.") @Test void createAnonymousChatRoomWhenNoToken() throws Exception { - // when // then mockMvc.perform(post("/api/chats/rooms") .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) @@ -60,13 +57,11 @@ void createAnonymousChatRoomWhenNoToken() throws Exception { @DisplayName("특정 채팅방의 메시지를 Cursor 방식으로 조회한다.") @Test void getMessagesWithCursorSuccess() throws Exception { - // given ChatRoom chatRoom = chatRoomRepository.save(ChatRoomFixture.chatRoom(1L, loginUser)); ChatBotMessage savedMsg = chatBotMessageRepository.save( ChatBotMessageFixture.chatBotMessage(chatRoom.getId(), null)); - // when // then mockMvc.perform(get("/api/chats/{chatroomId}", chatRoom.getId()) .param("size", "10") .header("Authorization", accessTokenOfUser) diff --git a/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotMessageRepositoryTest.java b/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotMessageRepositoryTest.java index 074bbc3..87264df 100644 --- a/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotMessageRepositoryTest.java +++ b/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotMessageRepositoryTest.java @@ -31,7 +31,6 @@ public class ChatBotMessageRepositoryTest extends DataMongoSupport { @Test @DisplayName("첫 페이지를 커서 기반으로 조회하면 최신 순으로 지정된 개수의 메시지를 반환하고 hasNext가 true이다.") void findMessagesPage() { - // given final Long CHAT_ROOM_ID = 1L; ChatRoom chatRoom = ChatRoomFixture.chatRoom(CHAT_ROOM_ID, null); @@ -51,12 +50,10 @@ void findMessagesPage() { } mongoTemplate.getDb().getCollection(COLLECTION_NAME).insertMany(docs); - // when PageRequest pageRequest = PageRequest.of(0, PAGE_SIZE); CursorPageResponse response = chatBotMessageRepository.findMessagesPage(chatRoom, pageRequest, null); - // then assertThat(response.item()).hasSize(PAGE_SIZE); assertThat(response.hasNext()).isTrue(); assertThat(response.nextCursor()).isNotNull(); @@ -101,11 +98,9 @@ void findMessagesPage_lastPage() { CursorPageResponse firstPage = chatBotMessageRepository.findMessagesPage(chatRoom, pageRequest, null); - // when CursorPageResponse secondPage = chatBotMessageRepository.findMessagesPage(chatRoom, pageRequest, firstPage.nextCursor()); - // then assertThat(secondPage.item()).hasSize(2); assertThat(secondPage.hasNext()).isFalse(); assertThat(secondPage.nextCursor()).isNull(); diff --git a/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotReviewRepositoryTest.java b/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotReviewRepositoryTest.java index 0cbc778..2fd6a54 100644 --- a/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotReviewRepositoryTest.java +++ b/src/test/java/com/ureca/ufit/chatbot/repository/ChatBotReviewRepositoryTest.java @@ -36,16 +36,13 @@ void tearDown() { @DisplayName("커서 기반으로 챗봇 리뷰를 조회한다") @Test void getRatePlansByCursor() { - // given final int SIZE = 2; - // recommendPlan 더미 데이터 Map dummyPlan = Map.of( "aPlan", "aPlan", "bPlan", "bPlan" ); - // Fixture로 생성 ChatBotReview r1 = ChatBotReviewFixture.chatBotReview(5, dummyPlan); ChatBotReview r2 = ChatBotReviewFixture.chatBotReview(4, dummyPlan); ChatBotReview r3 = ChatBotReviewFixture.chatBotReview(3, dummyPlan); @@ -54,11 +51,9 @@ void getRatePlansByCursor() { chatBotReviewRepository.saveAll(List.of(r1, r2, r3, r4, r5)); - // when CursorPageResponse page1 = chatBotReviewRepository.getChatBotReviewByCursor(null, SIZE); - // then - 원하는 결과 assertAll( () -> assertThat(page1.item()).hasSize(SIZE), () -> assertThat(page1.item()) @@ -68,7 +63,6 @@ void getRatePlansByCursor() { () -> assertThat(page1.nextCursor()).isEqualTo(r4.getId()) ); - // } } diff --git a/src/test/java/com/ureca/ufit/chatbot/service/ChatRoomServiceTest.java b/src/test/java/com/ureca/ufit/chatbot/service/ChatRoomServiceTest.java index f3e9a91..cb16100 100644 --- a/src/test/java/com/ureca/ufit/chatbot/service/ChatRoomServiceTest.java +++ b/src/test/java/com/ureca/ufit/chatbot/service/ChatRoomServiceTest.java @@ -38,7 +38,6 @@ public class ChatRoomServiceTest { @Test @DisplayName("회원에 대해 기존 채팅방이 있을 때 기존 채팅방을 반환한다") public void getExistingChatRoom() { - // given String email = "test@email.com"; Long chatRoomId = 1L; @@ -48,11 +47,9 @@ public void getExistingChatRoom() { given(userRepository.getByEmail(email)).willReturn(user); given(chatRoomRepository.findByUser(user)).willReturn(Optional.of(existingChatRoom)); - // when ChatRoomCreateResponse result = chatRoomService.getOrCreateChatRoom( new CustomUserDetails(1L, email, "pass", Role.USER)); - // then assertThat(result.chatRoomId()).isEqualTo(chatRoomId); assertThat(result.isAnonymous()).isFalse(); then(chatRoomRepository).should(never()).save(any(ChatRoom.class)); @@ -61,7 +58,6 @@ public void getExistingChatRoom() { @Test @DisplayName("회원에 대해 기존 채팅방이 없을 때 새로운 채팅방을 생성하여 반환한다") public void getOrCreateChatRoom_NoChatRoom_CreatesAndReturnsNewChatRoom() { - // given String email = "test@email.com"; Long chatRoomId = 2L; @@ -72,11 +68,9 @@ public void getOrCreateChatRoom_NoChatRoom_CreatesAndReturnsNewChatRoom() { given(chatRoomRepository.findByUser(user)).willReturn(Optional.empty()); given(chatRoomRepository.save(any(ChatRoom.class))).willReturn(newChatRoom); - // when ChatRoomCreateResponse result = chatRoomService.getOrCreateChatRoom( new CustomUserDetails(1L, email, "pass", Role.USER)); - // then assertThat(result.chatRoomId()).isEqualTo(chatRoomId); assertThat(result.isAnonymous()).isFalse(); then(chatRoomRepository).should().save(any(ChatRoom.class)); @@ -85,16 +79,13 @@ public void getOrCreateChatRoom_NoChatRoom_CreatesAndReturnsNewChatRoom() { @Test @DisplayName("비회원 사용자인 경우 새 채팅방을 생성하고 isAnonymous가 true인 응답을 반환한다") public void getOrCreateChatRoom_AnonymousUser() { - // given Long chatRoomId = 3L; ChatRoom anonymousChatRoom = ChatRoomFixture.chatRoom(chatRoomId, null); given(chatRoomRepository.save(any(ChatRoom.class))).willReturn(anonymousChatRoom); - // when ChatRoomCreateResponse result = chatRoomService.getOrCreateChatRoom(null); - // then assertThat(result.chatRoomId()).isEqualTo(chatRoomId); assertThat(result.isAnonymous()).isTrue(); then(chatRoomRepository).should().save(any(ChatRoom.class)); diff --git a/src/test/java/com/ureca/ufit/global/profanity/ProfanityFilterTest.java b/src/test/java/com/ureca/ufit/global/profanity/ProfanityFilterTest.java index e8736b6..e922bbd 100644 --- a/src/test/java/com/ureca/ufit/global/profanity/ProfanityFilterTest.java +++ b/src/test/java/com/ureca/ufit/global/profanity/ProfanityFilterTest.java @@ -23,28 +23,22 @@ void setUp() { @DisplayName("욕설이 포함된 문장이면 금칙어 필터링이 작동된다.") @Test void testContainsBannedword() { - // given String text = "너는 정말 바보 같아!"; - // when boolean isBanned = profanityFilter.containsBannedword(text); - // then assertThat(isBanned).isTrue(); } @DisplayName("해킹 시도가 있는 문장이면 금칙어 필터링이 작동된다.") @Test void testContainsAttackPattern() { - // given String sqlInjection = "' OR 1=1 --"; String xss = ""; - // when boolean isSqlInjection = profanityFilter.containsAttackPattern(sqlInjection); boolean isXss = profanityFilter.containsAttackPattern(xss); - // then assertThat(isSqlInjection).isTrue(); assertThat(isXss).isTrue(); } @@ -52,16 +46,13 @@ void testContainsAttackPattern() { @DisplayName("우회 금칙어가 있는 문장이면 금칙어 필터링이 작동된다.") @Test void testBypassFilter() { - // given String input = "바 보"; String input2 = "바1보"; Set policies = Set.of(NUMBERS, WHITESPACES); - // when boolean isWhitespaces = profanityFilter.isBanned(input, policies); boolean isNumber = profanityFilter.isBanned(input2, policies); - // then assertThat(isWhitespaces).isTrue(); assertThat(isNumber).isTrue(); } @@ -69,14 +60,11 @@ void testBypassFilter() { @DisplayName("욕설과 해킹 시도가 없는 문장이면 금칙어 필터링이 작동하지 않는다.") @Test void testNoBanned() { - // given String text = "안녕하세요. 좋은 하루 보내세요."; Set policies = Set.of(NUMBERS, WHITESPACES); - // when boolean isBanned = profanityFilter.isBanned(text, policies); - // then assertThat(isBanned).isFalse(); } } \ No newline at end of file diff --git a/src/test/java/com/ureca/ufit/rateplan/repository/RatePlanQueryRepositoryTest.java b/src/test/java/com/ureca/ufit/rateplan/repository/RatePlanQueryRepositoryTest.java index ce45193..b5717d2 100644 --- a/src/test/java/com/ureca/ufit/rateplan/repository/RatePlanQueryRepositoryTest.java +++ b/src/test/java/com/ureca/ufit/rateplan/repository/RatePlanQueryRepositoryTest.java @@ -40,7 +40,6 @@ void tearDown() { @DisplayName("커서 기반으로 요금제 목록을 조회한다") @Test void getRatePlansByCursor() { - // given final int SIZE = 2; final String TYPE = "lowestPrice"; @@ -57,14 +56,12 @@ void getRatePlansByCursor() { TYPE ); - // when CursorPageResponse response2 = ratePlanQueryRepositoryImpl.getRatePlansByCursor( response1.nextCursor(), SIZE, TYPE ); - // then assertAll( () -> assertThat(response2.item().size()).isEqualTo(SIZE), () -> assertThat(response2.item().get(SIZE - 1).planName()).isEqualTo(plan4.getPlanName()), @@ -75,7 +72,6 @@ void getRatePlansByCursor() { @DisplayName("낮은 가격 순으로 요금제 목록을 조회한다.") @Test void getRatePlansOrderByLowestPrice() { - // given final int SIZE = 2; final String TYPE = "lowestPrice"; @@ -86,14 +82,12 @@ void getRatePlansOrderByLowestPrice() { RatePlan plan5 = RatePlanFixture.ratePlan("plan5", 300); ratePlanRepository.saveAll(List.of(plan1, plan2, plan3, plan4, plan5)); - // when CursorPageResponse response = ratePlanQueryRepositoryImpl.getRatePlansByCursor( null, SIZE, TYPE ); - // then assertAll( () -> assertThat(response.item().size()).isEqualTo(SIZE), () -> assertThat(response.item().get(SIZE - 1).planName()).isEqualTo(plan5.getPlanName()) @@ -103,7 +97,6 @@ void getRatePlansOrderByLowestPrice() { @DisplayName("높은 가격 순으로 요금제 목록을 조회한다.") @Test void getRatePlansOrderByHighestPrice() { - // given final int SIZE = 2; final String TYPE = "highestPrice"; @@ -114,14 +107,12 @@ void getRatePlansOrderByHighestPrice() { RatePlan plan5 = RatePlanFixture.ratePlan("plan5", 300); ratePlanRepository.saveAll(List.of(plan1, plan2, plan3, plan4, plan5)); - // when CursorPageResponse response = ratePlanQueryRepositoryImpl.getRatePlansByCursor( null, SIZE, TYPE ); - // then assertAll( () -> assertThat(response.item().size()).isEqualTo(SIZE), () -> assertThat(response.item().get(SIZE - 1).planName()).isEqualTo(plan4.getPlanName()) @@ -131,18 +122,15 @@ void getRatePlansOrderByHighestPrice() { @DisplayName("요금제 목록이 비어있을 때 빈 목록이 조회된다.") @Test void getEmptyWhenRatePlanIsEmpty() { - // given final int SIZE = 10; final String TYPE = "highestPrice"; - // when CursorPageResponse response = ratePlanQueryRepositoryImpl.getRatePlansByCursor( null, SIZE, TYPE ); - // then assertAll( () -> assertThat(response.item().size()).isZero(), () -> assertThat(response.hasNext()).isFalse(), @@ -153,7 +141,6 @@ void getEmptyWhenRatePlanIsEmpty() { @DisplayName("가격 내림차순으로 요금제 목록을 조회한다") @Test void getRatePlanPreviewsOrderByPriceDesc() { - // given final int PAGE_SIZE = 3; RatePlan plan1 = RatePlanFixture.ratePlan("5G 베이직", 35000); @@ -163,11 +150,9 @@ void getRatePlanPreviewsOrderByPriceDesc() { Pageable pageable = PageRequest.of(0, PAGE_SIZE); - // when Page result = ratePlanQueryRepositoryImpl.getRatePlanPreviews(pageable, "PRICE_DESC"); - // then assertAll( () -> assertThat(result.getContent().size()).isEqualTo(3), () -> assertThat(result.getTotalElements()).isEqualTo(3), @@ -180,7 +165,6 @@ void getRatePlanPreviewsOrderByPriceDesc() { @DisplayName("가격 오름차순으로 요금제 목록을 조회한다") @Test void getRatePlanPreviewsOrderByPriceAsc() { - // given final int PAGE_SIZE = 3; RatePlan plan1 = RatePlanFixture.ratePlan("5G 베이직", 35000); @@ -190,11 +174,9 @@ void getRatePlanPreviewsOrderByPriceAsc() { Pageable pageable = PageRequest.of(0, PAGE_SIZE); - // when Page result = ratePlanQueryRepositoryImpl.getRatePlanPreviews(pageable, "PRICE_ASC"); - // then assertAll( () -> assertThat(result.getContent().size()).isEqualTo(3), () -> assertThat(result.getTotalElements()).isEqualTo(3), @@ -207,7 +189,6 @@ void getRatePlanPreviewsOrderByPriceAsc() { @DisplayName("페이지네이션이 정상적으로 동작한다") @Test void getRatePlanPreviewsPaginationWorks() { - // given RatePlan plan1 = RatePlanFixture.ratePlan("5G 베이직", 35000); RatePlan plan2 = RatePlanFixture.ratePlan("5G 프리미어", 115000); RatePlan plan3 = RatePlanFixture.ratePlan("5G 라이트", 55000); @@ -215,11 +196,9 @@ void getRatePlanPreviewsPaginationWorks() { Pageable pageable = PageRequest.of(0, 2); - // when Page result = ratePlanQueryRepositoryImpl.getRatePlanPreviews(pageable, "PRICE_DESC"); - // then assertAll( () -> assertThat(result.getContent().size()).isEqualTo(2), () -> assertThat(result.getTotalElements()).isEqualTo(3), @@ -230,15 +209,12 @@ void getRatePlanPreviewsPaginationWorks() { @DisplayName("저장된 요금제가 없을 때 빈 목록을 조회한다") @Test void getRatePlanPreviewsEmptyWhenNoData() { - // given final int PAGE_SIZE = 10; Pageable pageable = PageRequest.of(0, PAGE_SIZE); - // when Page result = ratePlanQueryRepositoryImpl.getRatePlanPreviews(pageable, "PRICE_DESC"); - // then assertAll( () -> assertThat(result.getContent().size()).isZero(), () -> assertThat(result.getTotalElements()).isZero(), @@ -249,16 +225,13 @@ void getRatePlanPreviewsEmptyWhenNoData() { @DisplayName("존재하는 ID로 요금제 상세 정보를 조회한다") @Test void getRatePlanDetailReturnsData() { - // given RatePlan plan = RatePlanFixture.ratePlan("5G 프리미어", 115000); RatePlan savedPlan = ratePlanRepository.save(plan); String id = savedPlan.getId(); - // when Optional result = ratePlanQueryRepositoryImpl.getRatePlanDetailById(id); - // then assertThat(result).isPresent(); RatePlanDetailResponse detail = result.get(); @@ -278,14 +251,11 @@ void getRatePlanDetailReturnsData() { @DisplayName("존재하지 않는 ID로 요금제 상세 정보를 조회하면 빈 값을 반환한다") @Test void getRatePlanDetailReturnsEmptyForInvalidId() { - // given String fakeId = "666f6f2d6261722d71757778"; - // when Optional result = ratePlanQueryRepositoryImpl.getRatePlanDetailById(fakeId); - // then assertThat(result).isNotPresent(); } } diff --git a/src/test/java/com/ureca/ufit/user/controller/UserControllerTest.java b/src/test/java/com/ureca/ufit/user/controller/UserControllerTest.java index edf3c5a..5ef625a 100644 --- a/src/test/java/com/ureca/ufit/user/controller/UserControllerTest.java +++ b/src/test/java/com/ureca/ufit/user/controller/UserControllerTest.java @@ -71,7 +71,6 @@ void cleanUp() { SecurityContextHolder.clearContext(); } - // 로그인 관련 테스트 시작 @DisplayName("사용자/관리자가 로그인 하면 refreshToken 및 accessToken이 발급된다.") @Test void loginTest() throws Exception { @@ -92,15 +91,12 @@ void loginTest() throws Exception { @DisplayName("존재하지 않는 이메일로 로그인 시도 시 404을 반환한다.") @Test void loginWithNonexistentEmail() throws Exception { - // given LoginRequest request = new LoginRequest("nonexistent@email.com", "password"); - // when mockMvc.perform(post("/api/auth/login") .contentType(MediaType.APPLICATION_JSON) .content(toJson(request)) ) - //then .andExpect(status().isNotFound()) .andExpect(jsonPath("$.code") .value(UserErrorCode.USER_NOT_FOUND.name())) @@ -112,10 +108,8 @@ void loginWithNonexistentEmail() throws Exception { @DisplayName("잘못된 비밀번호로 로그인 시도 시 400을 반환한다.") @Test void loginWithWrongPassword() throws Exception { - // given LoginRequest request = new LoginRequest("test@email.com", "wrongPassword"); - // when mockMvc.perform(post("/api/auth/login") .contentType(MediaType.APPLICATION_JSON) .content(toJson(request)) @@ -127,13 +121,10 @@ void loginWithWrongPassword() throws Exception { .value(UserErrorCode.USER_PASSWORD_MISMATCH.getMessage()) ); } - //-------------------------// - // 로그아웃 관련 테스트 시작 @DisplayName("로그인 후 로그아웃하면 refreshToken 삭제 및 accessToken 블랙리스트 처리된다.") @Test void logoutTest() throws Exception { - // 로그인 LoginRequest loginRequest = new LoginRequest(email, password); var loginResult = mockMvc.perform(post("/api/auth/login") @@ -146,7 +137,6 @@ void logoutTest() throws Exception { .getValue(); String bearerToken = loginResult.getResponse().getHeader(AUTH_HEADER); - // 로그아웃 mockMvc.perform(post("/api/auth/logout") .header(AUTH_HEADER, bearerToken) .cookie(new Cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken))) @@ -177,13 +167,10 @@ void logoutWithInvalidAccessToken() throws Exception { .andExpect(jsonPath("$.code").value(CommonErrorCode.INVALID_TOKEN.name())) .andExpect(jsonPath("$.message").value(CommonErrorCode.INVALID_TOKEN.getMessage())); } - //-------------------------// - // 토큰 재발급 관련 테스트 시작 @DisplayName("accessToken이 만료되지 않으면 재발급 요청 시 예외가 발생한다.") @Test void reissueFailsIfAccessTokenIsStillValid() throws Exception { - // 로그인으로 유효한 accessToken, refreshToken 발급 LoginRequest loginRequest = new LoginRequest(email, password); var loginResult = mockMvc.perform(post("/api/auth/login") @@ -195,7 +182,6 @@ void reissueFailsIfAccessTokenIsStillValid() throws Exception { String validAccessToken = loginResult.getResponse().getHeader(AUTH_HEADER); String validRefreshToken = loginResult.getResponse().getCookie(REFRESH_TOKEN_COOKIE_NAME).getValue(); - // accessToken이 아직 유효한 상태로 재발급 시도 mockMvc.perform(post("/api/auth/reissue/token") .header(AUTH_HEADER, validAccessToken) .cookie(new Cookie(REFRESH_TOKEN_COOKIE_NAME, validRefreshToken))) @@ -215,7 +201,6 @@ void reissueFailsWithoutAuthorizationHeader() throws Exception { @DisplayName("accessToken이 만료되었을 경우 refreshToken을 통해 재발급할 수 있다.") @Test void reissueSucceedsWhenAccessTokenIsExpired() throws Exception { - // 1. 회원가입 → 로그인하여 토큰 발급 LoginRequest loginRequest = new LoginRequest(email, password); var loginResult = mockMvc.perform(post("/api/auth/login") @@ -227,7 +212,6 @@ void reissueSucceedsWhenAccessTokenIsExpired() throws Exception { String refreshToken = loginResult.getResponse().getCookie(REFRESH_TOKEN_COOKIE_NAME).getValue(); String expiredAccessToken = JwtUtil.createToken(email, "access", secretKey, 1); - // 3. 재발급 요청 var reissueResult = mockMvc.perform(post("/api/auth/reissue/token") .header(AUTH_HEADER, BEARER_PREFIX + expiredAccessToken) .cookie(new Cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken))) @@ -237,7 +221,6 @@ void reissueSucceedsWhenAccessTokenIsExpired() throws Exception { .andExpect(cookie().exists(REFRESH_TOKEN_COOKIE_NAME)) .andReturn(); - // 4. 응답 토큰 확인 String newAccessToken = reissueResult.getResponse().getHeader(AUTH_HEADER); String newRefreshToken = Objects.requireNonNull( reissueResult.getResponse().getCookie(REFRESH_TOKEN_COOKIE_NAME)).getValue(); @@ -263,7 +246,6 @@ void reissueWithTamperedRefreshToken() throws Exception { @DisplayName("블랙리스트에 등록된 accessToken으로 재발급 시도 시 401 반환") @Test void reissueWithBlacklistedAccessToken() throws Exception { - // 1. 로그인 LoginRequest loginRequest = new LoginRequest(email, password); var loginResult = mockMvc.perform(post("/api/auth/login") .contentType(MediaType.APPLICATION_JSON) @@ -273,10 +255,8 @@ void reissueWithBlacklistedAccessToken() throws Exception { String accessToken = loginResult.getResponse().getHeader(AUTH_HEADER).substring(7); String refreshToken = loginResult.getResponse().getCookie(REFRESH_TOKEN_COOKIE_NAME).getValue(); - // 2. 블랙리스트에 등록 redisTemplate.opsForValue().set(BLACKLIST_PREFIX + accessToken, "logout"); - // 3. 재발급 시도 mockMvc.perform(post("/api/auth/reissue/token") .header(AUTH_HEADER, BEARER_PREFIX + accessToken) .cookie(new Cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken))) diff --git a/src/test/java/com/ureca/ufit/user/filter/JwtFilterTest.java b/src/test/java/com/ureca/ufit/user/filter/JwtFilterTest.java index bff4d98..59d60ae 100644 --- a/src/test/java/com/ureca/ufit/user/filter/JwtFilterTest.java +++ b/src/test/java/com/ureca/ufit/user/filter/JwtFilterTest.java @@ -47,22 +47,18 @@ void setUp() { @DisplayName("화이트리스트 URI는 필터링 하지 않는다") @Test void whiteListFilteringTest() throws ServletException, IOException { - // given MockHttpServletRequest request = new MockHttpServletRequest("GET", "/swagger-ui/index.html"); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - // when jwtFilter.doFilter(request, response, filterChain); - // then verify(filterChain, times(1)).doFilter(request, response); } @DisplayName("유효한 토큰이 존재하면 인증객체를 설정한다") @Test void validTokenTest() throws Exception { - // given String email = "user@example.com"; String validToken = "valid.token.value"; @@ -76,21 +72,17 @@ void validTokenTest() throws Exception { when(redisTemplate.hasKey("blacklist:" + validToken)).thenReturn(false); when(userDetailsService.loadUserByUsername(email)).thenReturn(mockUser); - // static mock try (MockedStatic mockedJwtUtil = mockStatic(JwtUtil.class)) { mockedJwtUtil .when(() -> JwtUtil.validateAccessToken(validToken, secretKey)) - .thenCallRealMethod(); // 또는 .doNothing() 불가, void는 따로 처리 ↓ + .thenCallRealMethod(); - // 실제로는 아무 일도 하지 않도록 설정 mockedJwtUtil.when(() -> JwtUtil.validateAccessToken(validToken, secretKey)).thenAnswer(inv -> null); mockedJwtUtil.when(() -> JwtUtil.getEmail(validToken, secretKey)).thenReturn(email); - // when jwtFilter.doFilter(request, response, filterChain); - // then verify(userDetailsService).loadUserByUsername(email); verify(filterChain).doFilter(request, response); } @@ -99,12 +91,10 @@ void validTokenTest() throws Exception { @DisplayName("토큰이 없고 Public이 아니면 예외가 발생한다.") @Test void isNotPublicTest() { - // given MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/protected"); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - // then assertThatThrownBy(() -> jwtFilter.doFilter(request, response, filterChain)) .isInstanceOf(RestApiException.class) .hasMessageContaining(CommonErrorCode.NOT_EXIST_BEARER_SUFFIX.getMessage()); diff --git a/src/test/java/com/ureca/ufit/user/filter/LoginFilterTest.java b/src/test/java/com/ureca/ufit/user/filter/LoginFilterTest.java index 61d58be..3c4ea90 100644 --- a/src/test/java/com/ureca/ufit/user/filter/LoginFilterTest.java +++ b/src/test/java/com/ureca/ufit/user/filter/LoginFilterTest.java @@ -36,7 +36,6 @@ void setUp() { @DisplayName("로그인 요청을 정상적으로 파싱하고 인증을 위임한다") @Test void loginFilterTest() throws IOException, ServletException { - // given LoginRequest loginRequest = new LoginRequest("test@example.com", "password123"); ObjectMapper objectMapper = new ObjectMapper(); byte[] requestBody = objectMapper.writeValueAsBytes(loginRequest); @@ -53,10 +52,8 @@ void loginFilterTest() throws IOException, ServletException { when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class))) .thenReturn(dummyAuth); - // when Authentication result = loginFilter.attemptAuthentication(request, response); - // then assertThat(result).isNotNull(); verify(authenticationManager, times(1)).authenticate(any(UsernamePasswordAuthenticationToken.class)); } diff --git a/src/test/java/com/ureca/ufit/user/provider/LoginProviderTest.java b/src/test/java/com/ureca/ufit/user/provider/LoginProviderTest.java index 46ab2a3..bbef82a 100644 --- a/src/test/java/com/ureca/ufit/user/provider/LoginProviderTest.java +++ b/src/test/java/com/ureca/ufit/user/provider/LoginProviderTest.java @@ -37,7 +37,6 @@ class LoginProviderTest { @DisplayName("정상 로그인 시 Authentication 객체를 반환한다.") @Test void authenticateSuccess() { - // given UserDetails userDetails = User.withUsername(EMAIL) .password(ENCODED_PASSWORD) @@ -50,10 +49,8 @@ void authenticateSuccess() { when(userDetailsService.loadUserByUsername(EMAIL)).thenReturn(userDetails); when(passwordEncoder.matches(RAW_PASSWORD, ENCODED_PASSWORD)).thenReturn(true); - // when Authentication result = loginProvider.authenticate(token); - // then assertThat(result.isAuthenticated()).isTrue(); assertThat(result.getPrincipal()).isEqualTo(userDetails); } diff --git a/src/test/java/com/ureca/ufit/user/service/AuthServiceTest.java b/src/test/java/com/ureca/ufit/user/service/AuthServiceTest.java index 2b1c675..f0522e7 100644 --- a/src/test/java/com/ureca/ufit/user/service/AuthServiceTest.java +++ b/src/test/java/com/ureca/ufit/user/service/AuthServiceTest.java @@ -46,7 +46,6 @@ class AuthServiceTest { @DisplayName("토큰 재발급시 어세스토큰과 리프레시토큰이 모두 재발급 된다.(RTR)") @Test void reissueTokenSuccess() { - // given String email = "user@example.com"; String accessToken = "access.token.value"; String bearerToken = BEARER_PREFIX + accessToken; @@ -68,10 +67,8 @@ void reissueTokenSuccess() { () -> JwtUtil.updateRefreshTokenCookie(response, newRefreshToken, REFRESH_TOKEN_EXPIRED_MS / 1000)) .thenCallRealMethod(); - // when authService.reissueToken(bearerToken, refreshToken, response); - // then verify(refreshTokenRepository).deleteById(refreshToken); ArgumentCaptor captor = ArgumentCaptor.forClass(RefreshToken.class); verify(refreshTokenRepository).save(captor.capture()); diff --git a/src/test/java/com/ureca/ufit/user/service/UserServiceTest.java b/src/test/java/com/ureca/ufit/user/service/UserServiceTest.java index 05b10bd..154bbf6 100644 --- a/src/test/java/com/ureca/ufit/user/service/UserServiceTest.java +++ b/src/test/java/com/ureca/ufit/user/service/UserServiceTest.java @@ -36,7 +36,6 @@ public class UserServiceTest { @DisplayName("사용자/관리자는 정상적으로 회원가입할 수 있다.") @Test void registerTest() { - // given RegisterRequest request = new RegisterRequest( "test@email.com", "test123!@#", 28, 175, @@ -53,10 +52,8 @@ void registerTest() { ); when(userRepository.save(Mockito.any(User.class))).thenReturn(savedUser); - // when RegisterResponse response = userService.register(request); - // then assertThat(response.success()).isTrue(); } }