Spring Component Test

iqpizza6349·2023년 11월 21일
0

Spring

목록 보기
5/6
post-thumbnail

개발을 자주 하면 할 수록 테스트가 점점 중요하다는 생각을 가지게 된다.
발생할 문제를 미연에 방지할 수도 있고, 정상적으로 동작되는 지 역시 알 수 있기 때문이다.

이 중에서 스프링을 오래 다뤄분 들이라면 이미 알고 계시겠지만, 스프링을 통한 테스트를 자주 하지 않은 분들을 위해 글을 작성하게 되었다.

스프링에서 테스트하는 방법

스프링에서 테스트하는 방법은 여러 가지가 있지만, 가장 대표적인 방법은 아마 @SpringBootTest 어노테이션을 통해 테스트 클래스로 지정하는 것이다.

그리고 레이어마다 각기 편의한 어노테이션들 역시 제공해주고 있다.
예를 들면 Jpa 환경에서는 @DataJpaTest를, Controller, Filter, WebMvcConfigurer 들을
테스트하고 싶다면 @WebMvcTest을, REST 통신의 JSON 형식이 예상대로 응답을 반환하는 지를 테스트할 때는 @RestClientTest을 사용하는 등 여러 어노테이션들을 제공해주고 있다.

그렇다면, 커스텀 컴포넌트를 테스트해야 한다면 어떻게 하는 것이 좋을 까?

커스텀 컴포넌트 테스트하는 방법

우선, 모든 컴포넌트를 로드하는 @SpringBootTest가 방법이 될 수 있지만, 개인적으로 추천하진 않는다. 좋은 테스트를 위해서는 FIRST를 지키는 것이 좋다.
(FIRST에 대해서는 이 링크를 참고하자.)

FIRST에서 말하기를 "테스트는 빠르게 동작하여 자주 시연할 수 있어야한다."
빠른 동작을 위해서는 @SpringBootTest는 사용해서는 안된다.
필요하지 않은 컴포넌트들까지 전부 로드하기 때문이다.

컴포넌트 테스트 환경

필자가 가장 추천하는 방법은 @ContextConfiguration을 기반으로 하는 테스트이다.
꼭 필요한 컴포넌트들만 로드할 수 있기에 가볍기 때문이다.
또, 필요에 따라서 클래스를 추가하거나 할 수 있기 때문이다.

@ContextConfiguration(classes = {
    ...추가할 컴포넌트 클래스들
})

실전 테스트

아래는 실제 필자가 JWT 토큰 생성 및 검증을 테스트한 코드 중 일부이다.

@ExtendWith(SpringExtension.class)
@TestPropertySource(locations = "classpath:test.properties")
@ContextConfiguration(classes = {
        TokenManager.class,
        TokenProperty.class,
        JsonWebTokenGenerator.class /** 반드시 구현체를 주입받아야하기에 구현체 직접 주입 */
})
@ConfigurationPropertiesScan(basePackageClasses = TokenProperty.class)
class TokenManagerTest {
    
    @Autowired
    private TokenManager tokenManager;
    
    @ParameterizedTest
    @ValueSource(longs = { 1, 12, 144, 99, 51143, 573 }
	void generateAndVerifyToken(long id) {
        //given -> already given by parameter
        
        //when
        final String token = tokenManager.generateAccessToken(id);
        
        //verify
        assertThat(token).isNotBlank();
        assertThat(tokenManager.authenticateToken(token, TokenType.ACCESS))
                .isEqualTo(id);
    }
}

@ConfigurationProperties를 사용하는 경우

@ConfigurationProperties를 사용하는 클래스가 있는 경우, 그냥 동작하는 경우도 있지만
만일 되지 않는 경우 직접 @ConfigurationPropertiesScan을 통해 지정해주면 동작할 것이고,
실제 프로퍼티와 다른 프로퍼티를 지정해주고 싶은 경우, @TestPropertySource를 사용하면 된다.

만일 구현체가 아닌 인터페이스를 @ContextConfiguration에 추가한 경우

Cannot process locations AND classes for context configuration ...(중략) configure one or the other, but not both

이라는 에러가 발생하기에 반드시 구현체를 작성해야한다.

profile
coffee.drinkUntilEmpty();

0개의 댓글