Spring Boot 어플리케이션에서 JUnit과 Mockito를 사용해 테스트하던 중 UserAuthorizationUtil.getLoginUser()를 호출하는 코드에서 다음과 같은 예외가 발생했다.
java.lang.IllegalArgumentException: 인증된 사용자가 없습니다.
at com.shineidle.tripf.common.util.UserAuthorizationUtil.getUserDetails(UserAuthorizationUtil.java:19)
at com.shineidle.tripf.common.util.UserAuthorizationUtil.getLoginUser(UserAuthorizationUtil.java:48)
1. SecurityContextHolder의 인증 정보 부족
UserAuthorizationUtil.getLoginUser() 내부에서는 SecurityContextHolder.getContext().getAuthentication() 을 호출해 현재 로그인한 사용자를 가져오는데, 테스트 환경에서는 SecurityContextHolder가 초기화되지 않이 null이 반환되었다.
2. Spring Security의 Authentication 객체 미설정
Spring Security는 HTTP 요청을 처리할 때 SecurityConext를 자동으로 설정하지만, 단위 테스트 환경에서는 이를 직접 설정해야 한다. 그렇지 않으면 authentication == null || !authentication.isAuthenticated() 조건을 만족하여 IllegalArgumentException("인증된 사용자가 없습니다.") 예외가 발생한다.
테스트 실행 전에 SecurityContextHolder에 가짜 인증 정보를 설정하여 UserAuthorizationUtil.getLoginUser()가 정상적으로 동작하도록 만든다
import org.junit.jupiter.api.BeforeEach;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import com.shineidle.tripf.common.security.UserDetailsImpl;
@BeforeEach
void setUp() {
user = new User();
user.setId(1L);
user.setEmail("test@example.com");
UserDetailsImpl userDetails = new UserDetailsImpl(user);
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(auth);
SecurityContextHolder.setContext(securityContext);
}
이렇게 설정하면 SecurityContextHolder가 인증 정보를 갖게 되어, UserAuthorizationUtil.getLoginUser() 호출 시 정상적으로 User 객체를 반환한다.
UserAuthorizationUtil이 SecurityContextHolder에 의존하는 것이 아닌, 특정 객체를 참조하는 방식이라면 ReflectionTestUtils를 사용하여 내부 필드를 강제로 설정하는 방법도 있다.
import org.springframework.test.util.ReflectionTestUtils;
@BeforeEach
void setUp() {
user = new User();
user.setId(1L);
UserDetailsImpl userDetails = new UserDetailsImpl(user);
ReflectionTestUtils.setField(UserAuthorizationUtil.class, "authenticatedUser", userDetails);
}
이 방법은 SecurityContextHolder가 아닌 특정 필드를 참조하는 경우에만 유효하다.
위 방법을 적용한 후 다시 테스트를 실행한 결과 예외 발생 없이, 정상적으로 테스트 코드가 실행되었다.