@SpringBootTest
는 스프링 부트에서 통합 테스트를 실행하기 위해 사용되는 어노테이션이다. 먼저, @SpringBootTest
는 @SpringBootApplication
을 찾아서, 테스트를 위한 빈을 생성해준다. 덕분에, 테스트 환경에서 동일하게 의존성 주입(@AutoWired
)이 가능하다.
@SpringBootTest 어노테이션에는 webEnvironment
값을 설정할 수 있다.
기본값은 WebEnvironment.MOCK
이다. 기본 값을 사용하면, 실제 Servlet Container를 생성하지 않고, MockMvc
를 생성하여 테스트를 수행한다. MockMvc
는 어플리케이션을 서버에 배포하지 않고, 스프링의 MVC 동작을 재현하기 위해 사용되는 클래스이다.
기본 값을 WebEnvironment.RANDOM_PORT
로 바꾸면, 실제 내장 톰캣을 실행하고, 스프링 어플리케이션을 서버에 배포한다. 따라서, RestTemplate
혹은 WebTestClient
를 사용한 테스트가 가능하다.
@MockBean
은 스프링 부트에서 테스트를 위해 제공하는 어노테이션이다. @MockBean
어노테이션을 사용하면, 스프링에서 기존에 선언된 Bean 대신 MockBean
객체를 생성하여 주입한다. MockBean
객체는 given 구문을 통해 테스트 환경에서 어떻게 동작할지 개발자가 직접 선언하여, 항상 일정한 결과를 반환하도록 할 수 있다.
이러한 성질로, MockBean
객체는 하나의 클래스에 포함된 의존성 객체들 중, 실제로 테스트하고 싶은 부분과 그렇지 않은 부분을 분리하는데 유용하다.
예를 들어, Controller
에서 Service
와 관련된 기능을 테스트하려고 한다. Service
의 기능을 테스트하려면 Repository
에서 데이터를 불러와야 한다고 가정하자. 이러한 경우, 실제 Service
기능에는 아무런 문제가 없음에도 불구하고, Repository
에 외존하는 코드에서 문제가 발생하여 테스트가 실패할 수 있다.
@MockBean
어노테이션을 활용하면, 항상 일정한 결과를 반환하는 Mock Repository
를 생성하여 테스트하고자 하는 영역에 집중할 수 있다.
@SpringBootTest
public class MemberServiceTest {
@AutoWired
private MemberService memberService;
@MockBean(name = memberRepository)
private MemberRepository memberRepository;
@Test
private 회원_유효성_검증() {
Member member = new Member();
member.setName("hello");
member.setId(0L);
// Mock Repository의 동작 방식을 정의한다.
given(memberRepository.findById(0L)
.willReturn(Optional.ofNullable(member));
Member result = memberService.getNameById(0L).get();
assertThat(result.getName()).isEqualTo(member.getName());
}
}
@Transactional
은 스프링 코드 실행 전후에 트랜젝션을 생성/커밋 해주는 기능을 수행한다.@Transactional
을 사용하면, 테스트 과정에서 수행된 insert 명령들이 반영되지 않고 DB는 테스트를 실행하기 이전 상태로 roll-back되어 독립된 테스트 환경을 보장한다.
@SpringBootTest
@Transactional
public class MemberServiceIntTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
void 회원가입() {
...
insert something to DB
...
// 만약, @Transactional 어노테이션이 없다면
// 다음 테스트 실행 시, 이전 테스트에서 삽입한 데이터가 이미 존재한다.
}
}