Security Context에 우리가 원하는 사용자의 정보를 넣어 테스트가 정상적으로 동작할 수 있도록 해보자.
테스트 케이스를 작성하다 보면 사용자 정보 변경, 로그인 된 사용자만 요청가능한 API를 테스트하는 경우가 있다.
그러기 위해서는 Secutiry Context에 사용자 정보가 들어있어야 한다.
기본적으로 Spring Secutity를 사용하여 로그인 서비스가 구성되어있다는 가정하에 진행한다.
WithSecurityContextFactory
WithSecurityContextFactory는 SecutiryContext를 생성하여 테스트 시 사용할 수 있도록 해주는 인터페이스이다.
우리는 이 인터페이스의 구현체를 작성하여 사용할 것 이다.
createSecutiryContext 메서드의 파라미터를 보면 어노테이션을 받는 것을 알 수 있다.
우리는 이 어노테이션을 작성하여 Context가 필요한 테스트 케이스 메서드에서 사용할 것 이다.
메서드의 진행과정은 다음과 같다.
- AccountTemplate를 통해 Account객체를 생성한다.
- 생성한 Account객체를 통해 UserAccount를 생성한다.
- UserAccount는 UserDetails를 구현한 User를 상속받아 직접 작성한 클래스입니다.
- 생성한 UserAccount객체를 통해 UsernamePasswordAuthenticationToken을 생성한다.
- SecutiryContextHolder를 통해 비어있는 Context를 생성한다.
- 생성한 Context에 3번에서 생성한 토큰을 저장한다.
- 토큰이 저장된 Context를 반환한다.
public class WithUserDetailsSecurityContextFactory implements WithSecurityContextFactory<TestAccount> {
@Override
public SecurityContext createSecurityContext(TestAccount annotation) {
UserDetails userAccount = new UserAccount(AccountTemplate.account);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userAccount, "", userAccount.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(token);
return context;
}
}
Annotation
이제 우리가 생성한 Context를 사용하기 위해 어노테이션을 작성하고 이를 사용할 것이다.
- 작동 범위를 Runtime으로 설정한다.
- @WithSecurityContext를 통해 우리가 작성한 클래스를 설정한다.
이제 Context가 필요한 테스트 케이스 메서드에 이 어노테이션을 사용해주면 된다.
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithUserDetailsSecurityContextFactory.class)
public @interface TestAccount { }
사용 예시
WebMvcTest 하나의 예시를 들어보자.
아래는 SecurityContext에 사용자 정보가 들어있어야만 접근이 가능한 Controller 하나의 메서드 예이다.
메서드 파라미터 부분에 @AuthAccount를 통해 Account를 받는 것을 알 수 있다.
이것은 SecutiryContext에서 사용자 정보를 받아오는 방법이다. 어노테이션으로 로그인한 사용자 정보 받아오기
따라서 SecurityContext에 사용자 정보가 존재해야한다.
@PatchMapping("/password")
public CustomResponseEntity<Message> updatePassword(@AuthAccount Account account, @RequestBody PasswordRequest passwordRequest) {
accountService.updatePassword(account, passwordRequest);
return new CustomResponseEntity<>(
Message.of(HttpStatus.OK, AccountContent.PASSWORD_UPDATE_OK)
);
}
@TestAccount를 테스트 케이스 메서드에 사용하면 SecurityContext에 우리가 지정한 Account가 들어가있다.
따라서 정상적으로 위 @AuthAccount를 통해 Account객체를 얻을 수 있다.
@Test
@TestAccount
void updatePasswordFailByNotEqual() {
...
}
'개발 > Spring' 카테고리의 다른 글
Refresh Token 발급과 Access Token 재발급 (5) | 2022.02.11 |
---|---|
발급받은 JWT로 요청하기 (0) | 2022.02.11 |
[SpringBoot] FCM을 통해 Push알림 보내보기 (15) | 2022.02.10 |
[Spring] DispatcherServlet이란 무엇인가? (0) | 2022.02.10 |
[SpringBoot] Redis를 SpringBoot 프로젝트에서 사용해보자 (0) | 2022.02.10 |