-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5c2b417
commit d4633eb
Showing
2 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
src/test/java/net/teumteum/unit/core/security/JwtAuthenticationEntryPointTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package net.teumteum.unit.core.security; | ||
|
||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.BDDMockito.given; | ||
import static org.mockito.Mockito.times; | ||
import static org.mockito.Mockito.verify; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import net.teumteum.core.error.ErrorResponse; | ||
import net.teumteum.core.security.filter.JwtAuthenticationEntryPoint; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.mock.web.DelegatingServletOutputStream; | ||
import org.springframework.security.core.AuthenticationException; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
@DisplayName("JwtAuthenticationEntryPoint 단위 테스트의") | ||
public class JwtAuthenticationEntryPointTest { | ||
|
||
@Mock | ||
private ObjectMapper objectMapper; | ||
|
||
@Mock | ||
private AuthenticationException authenticationException; | ||
|
||
@Mock | ||
private HttpServletRequest request; | ||
|
||
@Mock | ||
private HttpServletResponse response; | ||
|
||
@InjectMocks | ||
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; | ||
|
||
@Nested | ||
@DisplayName("JwtAuthenticationFilter 에서 인증 예외가 발생시") | ||
class When_authentication_error_occurs_from_filter { | ||
|
||
@Test | ||
@DisplayName("알맞은 예외 메시지와 관련 응답을 반환한다.") | ||
void Return_error_response_with_message() throws IOException { | ||
// given | ||
var errorMessage = "Authentication Exception Occurred"; | ||
var outputStream = new ByteArrayOutputStream(); | ||
|
||
given(request.getAttribute("exception")).willReturn(errorMessage); | ||
given(response.getOutputStream()).willReturn(new DelegatingServletOutputStream(outputStream)); | ||
|
||
// when | ||
jwtAuthenticationEntryPoint.commence(request, response, authenticationException); | ||
|
||
// then | ||
verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
verify(objectMapper, times(1)).writeValue(any(OutputStream.class), any(ErrorResponse.class)); | ||
} | ||
} | ||
} |
142 changes: 142 additions & 0 deletions
142
src/test/java/net/teumteum/unit/core/security/JwtAuthenticationFilterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package net.teumteum.unit.core.security; | ||
|
||
import static net.teumteum.unit.common.SecurityValue.INVALID_ACCESS_TOKEN; | ||
import static net.teumteum.unit.common.SecurityValue.VALID_ACCESS_TOKEN; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.BDDMockito.given; | ||
import static org.mockito.Mockito.times; | ||
import static org.mockito.Mockito.verify; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import java.io.IOException; | ||
import net.teumteum.auth.service.AuthService; | ||
import net.teumteum.core.property.JwtProperty; | ||
import net.teumteum.core.security.UserAuthentication; | ||
import net.teumteum.core.security.filter.JwtAuthenticationFilter; | ||
import net.teumteum.core.security.service.JwtService; | ||
import net.teumteum.user.domain.User; | ||
import net.teumteum.user.domain.UserFixture; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.mock.web.MockHttpServletRequest; | ||
import org.springframework.mock.web.MockHttpServletResponse; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
@DisplayName("JwtAuthenticationFilter 단위 테스트의") | ||
public class JwtAuthenticationFilterTest { | ||
|
||
@Mock | ||
JwtService jwtService; | ||
|
||
@Mock | ||
AuthService authService; | ||
|
||
@Mock | ||
JwtProperty jwtProperty; | ||
|
||
@Mock | ||
JwtProperty.Access access; | ||
|
||
@Mock | ||
FilterChain filterChain; | ||
|
||
@InjectMocks | ||
JwtAuthenticationFilter jwtAuthenticationFilter; | ||
|
||
@Nested | ||
@DisplayName("API 요청시 JWT 파싱 및 회원 조회 로직은") | ||
class Api_request_with_valid_jwt_unit { | ||
|
||
@BeforeEach | ||
@AfterEach | ||
void clearSecurityContextHolder() { | ||
SecurityContextHolder.clearContext(); | ||
} | ||
|
||
@Test | ||
@DisplayName("유효한 JWT 인 경우, JWT 을 파싱하고 성공적으로 UserAuthentication 을 SecurityContext 에 저장한다.") | ||
void Parsing_jwt_and_save_user_in_security_context() throws ServletException, IOException { | ||
// given | ||
MockHttpServletRequest request = new MockHttpServletRequest(); | ||
MockHttpServletResponse response = new MockHttpServletResponse(); | ||
|
||
given(jwtProperty.getAccess()).willReturn(access); | ||
given(jwtProperty.getAccess().getHeader()).willReturn("Authorization"); | ||
given(jwtProperty.getBearer()).willReturn("Bearer"); | ||
|
||
request.addHeader(jwtProperty.getAccess().getHeader(), | ||
jwtProperty.getBearer() + " " + VALID_ACCESS_TOKEN); | ||
|
||
User user = UserFixture.getIdUser(); | ||
|
||
given(jwtService.validateToken(anyString())).willReturn(true); | ||
given(authService.findUserByAccessToken(anyString())).willReturn(user); | ||
|
||
// when | ||
jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); | ||
|
||
// then | ||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
assertThat(authentication).isInstanceOf(UserAuthentication.class); | ||
} | ||
|
||
@Test | ||
@DisplayName("유효하지 않은 JWT 와 함께 요청이 들어오면, 요청 처리를 중단하고 에러 메세지를 반환한다.") | ||
void Return_error_when_jwt_is_invalid() throws ServletException, IOException { | ||
// given | ||
MockHttpServletRequest request = new MockHttpServletRequest(); | ||
MockHttpServletResponse response = new MockHttpServletResponse(); | ||
|
||
given(jwtProperty.getAccess()).willReturn(access); | ||
given(jwtProperty.getAccess().getHeader()).willReturn("Authorization"); | ||
given(jwtProperty.getBearer()).willReturn("Bearer"); | ||
|
||
request.addHeader(jwtProperty.getAccess().getHeader(), | ||
jwtProperty.getBearer() + " " + INVALID_ACCESS_TOKEN); | ||
|
||
given(jwtService.validateToken(anyString())).willReturn(false); | ||
|
||
// when | ||
jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); | ||
|
||
// then | ||
assertThat(request.getAttribute("exception")).isEqualTo("요청에 대한 JWT 가 유효하지 않습니다."); | ||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
assertThat(authentication).isNull(); | ||
verify(filterChain, times(1)).doFilter(request, response); | ||
} | ||
|
||
@Test | ||
@DisplayName("JWT 가 존재하지 않는 경우, 요청 처리를 중단하고 에러 메세지를 반환한다.") | ||
void Return_error_when_jwt_is_not_exist() throws ServletException, IOException { | ||
// given | ||
MockHttpServletRequest request = new MockHttpServletRequest(); | ||
MockHttpServletResponse response = new MockHttpServletResponse(); | ||
|
||
given(jwtProperty.getAccess()).willReturn(access); | ||
given(jwtProperty.getAccess().getHeader()).willReturn("Authorization"); | ||
given(jwtProperty.getBearer()).willReturn("Bearer"); | ||
|
||
request.addHeader(jwtProperty.getAccess().getHeader(), | ||
jwtProperty.getBearer() + " "); | ||
|
||
// when | ||
jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); | ||
|
||
// then | ||
assertThat(request.getAttribute("exception")).isEqualTo("요청에 대한 JWT 정보가 존재하지 않습니다."); | ||
verify(jwtService, times(0)).validateToken(anyString()); | ||
} | ||
} | ||
} |