[Spring] 스프링 부트에서 테스트 실행하기

bluewhale·2021년 5월 22일
0

Spring

목록 보기
3/9
post-custom-banner

스프링 부트에서 통합 테스트 실행하기

@SpringBootTest

@SpringBootTest는 스프링 부트에서 통합 테스트를 실행하기 위해 사용되는 어노테이션이다. 먼저, @SpringBootTest@SpringBootApplication을 찾아서, 테스트를 위한 빈을 생성해준다. 덕분에, 테스트 환경에서 동일하게 의존성 주입(@AutoWired)이 가능하다.

webEnvironment

@SpringBootTest 어노테이션에는 webEnvironment값을 설정할 수 있다.

기본값은 WebEnvironment.MOCK이다. 기본 값을 사용하면, 실제 Servlet Container를 생성하지 않고, MockMvc를 생성하여 테스트를 수행한다. MockMvc는 어플리케이션을 서버에 배포하지 않고, 스프링의 MVC 동작을 재현하기 위해 사용되는 클래스이다.

기본 값을 WebEnvironment.RANDOM_PORT로 바꾸면, 실제 내장 톰캣을 실행하고, 스프링 어플리케이션을 서버에 배포한다. 따라서, RestTemplate 혹은 WebTestClient를 사용한 테스트가 가능하다.

@MockBean

@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은 스프링 코드 실행 전후에 트랜젝션을 생성/커밋 해주는 기능을 수행한다.@Transactional을 사용하면, 테스트 과정에서 수행된 insert 명령들이 반영되지 않고 DB는 테스트를 실행하기 이전 상태로 roll-back되어 독립된 테스트 환경을 보장한다.

@SpringBootTest
@Transactional
public class MemberServiceIntTest {
    
    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

    @Test
    void 회원가입() {
        ...
        insert something to DB 
        ... 
        // 만약, @Transactional 어노테이션이 없다면 
        // 다음 테스트 실행 시, 이전 테스트에서 삽입한 데이터가 이미 존재한다.
        }
    }
profile
안녕하세요
post-custom-banner

0개의 댓글