Spring Boot Slice Test
⛅️ Intro
Spring Boot 를 공부하다 보니 여러가지 테스트를 진행하는 과정에서 통합테스트 나 단위테스트 와 같은 단어들이 등장했다. 테스트의 중요성을 느끼고 기능이 완성될 때마다 충분한 테스트를 거치자고 다짐하기도 했고, 의미를 정확히 모르고 사용하는 것은 무의미하다 생각하여 이번 기회를 통해 정리해보고자 한다!
통합 테스트 (Integration Test) 란 ?
한마디로 여러 컴포넌트 간의 상호 작용을 통합적으로 테스트한다는 의미이다. 주로 Spring 의 @SpringBootTest 어노테이션을 사용하여 애플리케이션 컨텍스트를 로드하고, 실제 Bean 들과 상호작용하면서 애플리케이션의 통합을 확인한다.
애플리케이션의 설정과 모든 Bean을 로드하기 때문에 운영환경과 가장 유사한 테스트가 가능하고 전체적인 플로우를 쉽게 테스트할 수 있다는 장점이 있지만, 그만큼 시간이 오래걸리고 무거우며 테스트 단위가 크기 때문에 디버깅이 어렵다는 단점이 존재한다.
통합테스트 작성 단계
1. 애플리케이션 컨텍스트 로드
: @SpringBootTest 어노테이션을 사용하여 실제 애플리케이션 컨텍스트를 로드한다.
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MyIntegrationTest {
// 통합 테스트 코드 작성
}
2. 테스트 실행
: @Test 어노테이션을 사용하여 테스트 메소드를 정의한다.
import org.junit.jupiter.api.Test;
@SpringBootTest
class MyIntegrationTest {
@Test
void testSomething() {
// 통합 테스트 코드 작성
}
}
3. 자동 주입 및 상호 작용
: @Autowired 어노테이션을 사용하여 테스트에서 사용할 빈을 주입한다.
주로 MockMvc, TestRestRemplate 등을 사용하여 HTTP 요청을 수행하거나, 실제 서비스 메소드를 호출하고 결과를 검증한다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MyControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetMessage() throws Exception {
mockMvc.perform(get("/api/message"))
.andExpect(status().isOk());
}
}
* 테스트 데이터베이스 구성
: 통합 테스트에서 종종 실제 데이터베이스와 상호 작용해야 할 경우가 있다. 그러한 경우에 테스트 전용 데이터베이스를 사용한다.
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.TestPropertySource;
@DataJpaTest
@TestPropertySource(properties = {
"spring.datasource.url=jdbc:h2:mem:testdb"
})
class MyRepositoryIntegrationTest {
// ...
}
@SpringBootTest
- 스프링부트는 @SpringBootTest 어노테이션을 통해 스프링부트 애플리케이션 테스트에 필요한 대부분의 의존성을 제공.
- 통합 테스트를 제공하는 기본적인 스프링 부트 테스트 어노테이션.
- @SpringBootTest 어노테이션 사용시 Junit 버전에 따라 유의사항이 존재한다.
- Junit4 : @RunWith(SpringRunner.class) 와 함께 사용.
- Junit5 : 따로 명시할 필요 없음.
@SpringBootTest의 옵션
1. properties
1.1 프로퍼티를 {key = value} 형식으로 직접 추가가 가능하다.
@SpringBootTest(properties = {"name=yonghwan"})
public class SampleSpringBootTest {
@Value("${name}")
private String name;
@Test
public void testName(){
assertThat(name).isEqualTo("yonghwan");
}
}
1.2 프로퍼티의 키값으로 “spring.config.location”으로 설정하고 값으로 외부 파일을 설정하여 외부파일의 프로퍼티를 가져오는 것이 가능함
src/test/test.yml
yonghwan:
name: YongHwan
age: 20
@SpringBootTest 애노테이션의 properties 옵션을 이용하여 외부 파일을 다음과 같이 불러온다
@SpringBootTest(properties = {"spring.config.location = classpath:test.yml"})
public class SampleSpringBootTest {
@Value("${yonghwan.age}")
private int age;
@Test
public void testAge(){
assertThat(age).isEqualTo(20);
}
}
webEnvironment
- 웹 테스트 환경 구성이 가능하다.
- webEnvironment 파라미터를 이용하여 손쉽게 웹 테스트 환경을 선택할 수 있다.
- 웹 테스트 환경 종류
- Mock
- RANDOM_PORT
- DEFINED_PORT
- NONE
Mock
- 실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려운 경우, 가짜 객체를 만 들어 사용한다.
- WebApplicationContext를 불러오며 내장된 서블릿 컨테이너가 아닌 Mock 서블릿을 제공한다.
- @SpringBootTest 애노테이션의 webEnvironment 옵션의 기본값
- @AutoConfigureMockMvc 애노테이션을 함께 사용하여 MockMvc를 사용한 테스트 진행 가능하다.
- MockMvc는 브라우저에서 요청과 응답을 의미하는 객체. Controller 테스트 사용을 용이하게 해주는 라이브러리
- @AutoConfigureMockMvc 애노테이션은 Mock 테스트시 필요한 의존성을 제공한다.
@Autowired
MockMvc mockMvc;
RANDOM_PORT
- 내장된 WebApplicationContext를 불러오며 실제 서블릿 환경을 구성함
- 임의의 포트를 지정함
- 실제 서블릿 컨테이너를 사용하기 때문에 TestRestTemplate 사용
DEFINED_PORT
- RANDOM_PORT와 동일하게 실제 서블릿 환경을 구성하지만, 포트는 애플리케이션 프로퍼티에서 지정한 포트를 지정한다.
- 실제 서블릿 컨테이너를 사용하기 때문에 TestRestTemplate 사용
NONE
- 기본적인 ApplicationContext를 불러옴
TestRestTemplate란 무엇인가?
- 통합 테스트에 적합한 RestTemplate의 대안
- 4xx 및 5xx는 예외가 발생하지 않음. 대신 Response 엔티티 및 상태 코드를 통해 탐지될 수 있음
- 기본 인증 헤더가 선택적으로 포함될 수 있음 Apache Http Client 4.3.2 이상이 사용 가능한 경우 권장 클라이언트로 사용되며 기본적으로 쿠키 및 리다이렉션을 무시하도록 구성됨
- 주입 문제를 방지하기 위해 이 클래스는 의도적으로 RestTemplate를 확장하지 않음
- 기본 RestTemplate에 접근 권한이 필요한 경우 getRestTemplate()를 사용함
@Autowired
TestRestTemplate testRestTemplate;
@MockBean
- Mock 객체를 빈(Bean)으로써 등록할 수 있음
- @MockBean 애노테이션 적용시 스프링의 ApplicationContext는 Mock 객체를 빈으로 등록하며, @MockBean으로 선언된 객체와 같은 이름과 타입으로 이미 빈이 등록되어 있다면 해당 빈은 선언한 @MockBean으로 대체된다.
Root 개념을 구현할 때 유용한다.