인증된 사용자만 접근할 수 있는 기능을 테스트하기 위해 실제 DB에 저장되어있는 정보에 대응하는 인증된 Authentication이 필요하다. @WithSecurityContext
를 활용하여 커스텀 어노테이션을 만들면 된다.
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithAuthUser {
long usersId() default 1L;
String email() default "abc@gmail.com";
String password() default "1234abcd!";
String roles() default "USER";
}
@WithSecurityContext는 스프링 시큐리티 테스트용 SecurityContext를 만들겠다는 뜻이다. factory 값을 필수로 입력해야 하는데, 해당 클래스에서 @WithAuthUser어노테이션에 새로운 SecurityContext를 생성해 전달해야 한다.
WithSecurityContextFactory<WithAuthUser>
를 implement 밭는 클래스를 만든다.public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithAuthUser> {
@Override
public SecurityContext createSecurityContext(WithAuthUser annotation) {
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
CustomUserDetails principal =
new CustomUserDetails(annotation.usersId(), annotation.email(), annotation.password(), List.of(annotation.roles()));
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(annotation.roles()));
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null, authorities);
securityContext.setAuthentication(authentication);
return securityContext;
}
}
@WithSecurityContext어노테이션에 전달한 WithMockCustomUserSecurityContextFactory클래스를 만든다.
넘겨받은 WithAuthUser에서 Authentication 생성 후 SecurityContext에 넣어준 뒤 return 하면 된다.
@Test
@WithAuthUser
public void postTest() throws Exception {
....
}