728x90
1. JwtService.java Test 코드 작성
1) 기본 구조
@SpringBootTest
@Transactional
class JwtServiceImplTest {
@Autowired
UserRepository userRepository;
@Autowired
UserEntity userEntity;
@Autowired
EntityManager em;
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.access.expiration}")
private long accessTokenValidityInSeconds;
@Value("${jwt.refresh.expiration}")
private long refreshTokenValidityInSeconds;
@Value("${jwt.access.header}")
private String accessHeader;
@Value("${jwt.refresh.header}")
private String refreshHeader;
private static final String ACCESS_TOKEN_SUBJECT = "AccessToken";
private static final String REFRESH_TOKEN_SUBJECT = "RefreshToken";
private static final String USERNAME_CLAIM = "email";
private static final String BEARER = "Bearer";
String username = "username";
@BeforeEach
public void init() {
UserEntity user = UserEntity.builder().userEmail(username).userPwd("123456").userEmail("test@naver.com")
.userNikname("usernick").build();
userRepository.save(user);
clear();
}
private void clear() {
em.flush();
em.clear();
}
//토큰의 유효성 확인, 검증
private DecodedJWT getVerify(String token) {
return JWT.require(Algorithm.HMAC512(secret)).build().verify(token);
}
}
2) AccessToken, RefreshToken 발급 테스트
@Test
void createAccessToken_AccessToken_발급테스트() throws Exception {
// given, when
String accessToken = jwtService.createAccessToken(username);
DecodedJWT verify = getVerify(accessToken);
String subject = verify.getSubject();
String findUsername = verify.getClaim(USERNAME_CLAIM).asString();
// then
assertThat(findUsername).isEqualTo(username);
assertThat(subject).isEqualTo(ACCESS_TOKEN_SUBJECT);
}
@Test
void createAccessToken_RefreshToken_발급테스트() throws Exception{
// given, when
String refreshToken = jwtService.createRefreshToken();
DecodedJWT verify = getVerify(refreshToken);
String subject = verify.getSubject();
String username = verify.getClaim(USERNAME_CLAIM).asString();
// then
assertThat(subject).isEqualTo(REFRESH_TOKEN_SUBJECT);
assertThat(username).isNull(); //refreshToken은 username이 없어야 함
}
3) 토큰 유효성 테스트
@Test
void isTokenValid_토큰_유효성_검사() {
// given
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
// when, then
assertThat(jwtService.isTokenValid(accessToken)).isTrue();
assertThat(jwtService.isTokenValid(refreshToken)).isTrue();
}
4) RefreshToken 업데이트 테스트
@Test
void updateRefreshToken_refreshToken_업데이트() throws Exception {
// given
String refreshToken = jwtService.createRefreshToken();
jwtService.updateRefreshToken(username, refreshToken);
clear();
Thread.sleep(5000);
// when
String reIssueRefreshToken = jwtService.createRefreshToken();
jwtService.updateRefreshToken(username, reIssueRefreshToken);
clear();
// then
assertThrows(NoSuchElementException.class, () -> userRepository.findByRefreshToken(refreshToken).get());
assertThat(userRepository.findByRefreshToken(reIssueRefreshToken).get().getUserName()).isEqualTo(username);
}
5) RefreshToken 제거 테스트
@Test
void destoryRefreshToken_refreshToken_제거() throws Exception {
// given
String refreshToken = jwtService.createRefreshToken();
jwtService.updateRefreshToken(username, refreshToken);
clear();
// when
jwtService.destoryRefreshToken(username);
clear();
// then
assertThrows(Exception.class, () -> userRepository.findByRefreshToken(refreshToken).get());
UserEntity users = userRepository.findByUserName(username).get();
assertThat(users.getRefreshToken()).isNull();
}
6) AccessToken, RefreshToken 헤더 설정 테스트
@Test
void setAccessTokenHeader_AccessToken_헤더_설정() throws Exception {
// given
MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
jwtService.setAccessTokenHeader(mockHttpServletResponse, accessToken);
// when
jwtService.sendAccessAndRefreshToken(mockHttpServletResponse, accessToken, refreshToken);
// then
String headerAccessToken = mockHttpServletResponse.getHeader(accessHeader);
assertThat(headerAccessToken).isEqualTo(accessToken);
}
@Test
void setRefreshTokenHeader_RefreshToken_헤더_설정() throws Exception {
// given
MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
jwtService.setRefreshTokenHeader(mockHttpServletResponse, refreshToken);
// when
jwtService.sendAccessAndRefreshToken(mockHttpServletResponse, accessToken, refreshToken);
// then
String headerRefreshToken = mockHttpServletResponse.getHeader(refreshHeader);
assertThat(headerRefreshToken).isEqualTo(refreshToken);
}
MockHttpServletResponse?
Spring의 테스트 프레임워크에서 제공하는 클래스 중 하나로, HTTP 응답을 모의(Mock)하는 데 사용된다. 실제 HTTP 응답을 보내지 않고, 테스트 환경에서 HTTP 응답의 상태를 확인하거나 설정할 수 있도록 한다.
1) 응답 객체 모의 : 실제 HTTP 요청/응답을 보내지 않고도 HTTP 응답을 테스트할 수 있도록 해준다. 여기서는 setAccessTokenHeader() 실행 시 응답 헤더에 accessToken을 설정할 수 있다.
2) 응답 헤더 설정 확인 : setAccessTokenHeader() 호출은 mockHttpServletResponse의 헤더에 accessToken을 설정하는 코드이다. 이후 mockHttpServletResponse.getHeader()로 헤더값을 가져와 올바르게 설정되었는지 검증할 수 있다.
7) 토큰 전송 테스트
@Test
void sendAccessAndRefreshToken_토큰_전송() {
// given
MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
// when
jwtService.sendAccessAndRefreshToken(mockHttpServletResponse, accessToken, refreshToken);
// then
String headerAccessToken = mockHttpServletResponse.getHeader(accessHeader);
String headerRefreshToken = mockHttpServletResponse.getHeader(refreshHeader);
assertThat(headerAccessToken).isEqualTo(accessToken);
assertThat(headerRefreshToken).isEqualTo(refreshToken);
}
8) 토큰 추출 테스트
@Test
void extractAccessToken_AccessToken_추출() throws Exception {
// given
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
HttpServletRequest request = setRequset(accessToken, refreshToken);
// when
String extractAccessToken = jwtService.extractAccessToken(request)
.orElseThrow(() -> new Exception("예외 - Access 토큰이 없습니다."));
// then
assertThat(extractAccessToken).isEqualTo(accessToken);
assertThat(getVerify(extractAccessToken).getClaim(USERNAME_CLAIM).asString()).isEqualTo(username);
}
@Test
void extractRefreshToken_RefreshToken_추출() throws Exception {
// given
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
HttpServletRequest request = setRequset(accessToken, refreshToken);
// when
String extractRefreshToken = jwtService.extractRefreshToken(request)
.orElseThrow(() -> new Exception("예외 - Refresh 토큰이 없습니다."));
// then
assertThat(extractRefreshToken).isEqualTo(refreshToken);
// refreshToken은 username 없음
assertThat(getVerify(extractRefreshToken).getSubject()).isEqualTo(REFRESH_TOKEN_SUBJECT);
}
private HttpServletRequest setRequset(String accessToken, String refreshToken) throws IOException {
MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
jwtService.sendAccessAndRefreshToken(mockHttpServletResponse, accessToken, refreshToken);
String headerAccessToken = mockHttpServletResponse.getHeader(accessHeader);
String headerRefreshToken = mockHttpServletResponse.getHeader(refreshHeader);
MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
mockHttpServletRequest.addHeader(accessHeader, BEARER + headerAccessToken);
mockHttpServletRequest.addHeader(refreshHeader, BEARER + headerRefreshToken);
return mockHttpServletRequest;
}
9) username 추출 테스트
@Test
void extractUsername_username_추출() throws Exception {
// given
String accessToken = jwtService.createAccessToken(username);
String refreshToken = jwtService.createRefreshToken();
HttpServletRequest request = setRequset(accessToken, refreshToken);
String requestAccessToken = jwtService.extractAccessToken(request)
.orElseThrow(() -> new Exception("예외 - 토큰이 없습니다."));
// when
String extractUsername = jwtService.extractUsername(requestAccessToken)
.orElseThrow(() -> new Exception("예외 - 토큰 없음"));
// then
assertThat(extractUsername).isEqualTo(username);
}
[출처: https://ttl-blog.tistory.com/272#JwtService%20%EC%9E%91%EC%84%B1-1]
728x90
반응형
'Framework > Spring' 카테고리의 다른 글
[Spring / ToyProject] Spring Security 설정 - 3_3 (0) | 2025.01.17 |
---|---|
[Spring / ToyProject] Spring Security 설정 - 3_1 (1) | 2025.01.16 |
[Spring / ToyProject] Spring Security 설정 - 2_2 (0) | 2025.01.16 |
[Spring / ToyProject] Spring Security 설정 - 2_1 (0) | 2025.01.14 |
[Spring / ToyProject] 에러일지: Request failed with status code 403 (0) | 2025.01.08 |