SpringSecurity를 적용하면 컨트롤러 테스트에서도 인증이 필요하다. 이 때 가짜 사용자로 테스트를 실행할 수 있는 방법이 @WithMockUser
이다. MockUser는 아래와 같은 속성을 가진 MockUser를 만들고 WithSecurityContextFactory
에서 이를 이용해 Authentication
의 principal에 넣는다.
public @interface WithMockUser {
String value() default "user";
String username() default "";
String[] roles() default { "USER" };
String[] authorities() default {};
String password() default "password";
}
그러나 Jwt 또는 OAuth 등을 이용하여 커스텀 필터를 만든 경우 Authentication에 넣는 값도 달라진다. 이번 프로젝트 경우는 jwt과 Authentication의 principal에 userName
을 넣었는데 이 값은 위의 MockUser
에서 제공하지 않는다.
바로 @WithMockUser
로 테스트를 진행했더니 아래와 같은 에러가 발생하였다.
해결방법은 MockUser를 커스텀해서 테스트에 주입해준다.
@WithMockUser와 함께 진행되는 SecurityContext가 아닌 직접 만든 SecurityContext에 원하는 MockUser의 Authentication을 넣어서 테스트를 진행할 수 있다.
@WithMockCustomUser
어노테이션을 만든다.
: 가짜 사용자를 만든다.
WithMockCustomUser에는 @WithSecurityContext 어노테이션이 선언되어 있다. 값으로 주어진 factory를 이용하여 SecurityContext를 생성해서 테스트를 실행하라는 신호이다.
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithMockCustomUser {
String userName() default "user";
String role() default "USER";
}
WithMockCustomUserSecurityContextFactory
로직에서 token을 발급할 때와 비슷하게 구현하였다.
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithMockCustomUser> {
@Override
public SecurityContext createSecurityContext(WithMockCustomUser annotation) {
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
final UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(annotation.userName(), null,
List.of(new SimpleGrantedAuthority(annotation.role())));
securityContext.setAuthentication(authenticationToken);
return securityContext;
}
}
테스트에 @WithMockCustomUser를 달아준다.
@Test
@DisplayName("포스트 작성 성공")
@WithMockCustomUser
void post_add_success() throws Exception {
given(postService.add(postAddRequest, "user")).willReturn(new PostWorkResponse("포스트 등록 완료", 0));
mockMvc.perform(
post("/api/v1/posts")
...
}
참고 :
https://godekdls.github.io/Spring%20Security/testing/
https://jiwondev.tistory.com/270