JUnit 4 테스트 진행 과정(생명 주기)
JUnit으로 테스트를 진행할 때는 크게 다음과 같은 과정을 거친다.
- 개발자가 테스트 클래스를 정의
- @BeforeClass(JUnit 5에서는 @BeforeAll) 어노테이션이 적용된 메소드 실행 - 클래스 전체 테스트 전에 딱 한 번 실행
- 테스트 클래스 객체 생성
- @Before(JUnit 5에서는 @BeforeEach) 어노테이션이 붙은 메소드 실행 - 테스트 메소드 진행 전 선작업 필요한 경우 정의
- @Test 어노테이션이 붙은 테스트 메소드 실행
- 테스트 결과 저장
- @After(JUnit 5에서는 @AfterEach) 어노테이션이 붙은 메소드 실행 - 테스트 메소드 진행 후 다음 테스트에 영향 안 주도록 처리할 작업을 정의
- 각 테스트 메소드에 대해 3~7 반복
- @AfterClass(JUnit 5에서는 @AfterAll) 어노테이션이 적용된 메소드 실행 - 클래스 전체 테스트 종료 후 딱 한 번 실행
이 중에서 1번을 제외한 나머지 과정은 JUnit의 테스트 러너가 진행한다.
5번 과정에서 실행하는 @Test 메소드는 실제로 테스트를 진행하는 메소드이다.
테스트 대상 로직의 결과값이 개발자의 기댓값과 같은지를 assert 계열 메소드로 비교하게 되는데, 비교 결과가 같다면 통과이고 다르다면 Error 객체가 발생해 테스트가 실패하게 된다.
JUnit의 테스트 메소드를 진행하는 과정에서 Error, 또는 Exception이 발생하는 경우 JUnit은 테스트 실패로 간주한다.
assert 계열 메소드는 테스트 실패시 Error를 던지고, assume 계열 메소드는 테스트 실패시 Exception을 던진다.
JUnit의 테스트 러너
테스트 러너는 개발자가 정의한 테스트 클래스의 객체를 생성하고 객체의 테스트 메소드를 실행한 뒤 성공 결과를 확인하는 객체이다.
즉, JUnit을 이용한 테스트 진행의 주체가 바로 테스트 러너라고 할 수 있다.
JUnit 4 기준 기본으로 사용되는 테스트 러너는 BlockJUnit4ClassRunner이다.
SpringRunner
스프링 프로젝트에 대해 테스트를 진행하고 싶을 때는 기본 테스트 러너를 확장한 SpringRunner(SpringJUnit4ClassRunner)를 사용할 수 있다.
기본 러너 대신 스프링 러너를 사용하면 JUnit 테스트 환경에서 ApplicationContext(스프링 컨테이너)가 만들어져 활용할 수 있고, 컨텍스트에 빈을 추가하기 위해 @Autowired, @MockBean 등의 어노테이션을 사용할 수 있다.
이때 @Autowired, @MockBean으로 등록된 것들만 ApplicatonContext에 추가하기 때문에 테스트 실행 과정이 가벼워진다는 장점이 존재한다.
테스트 러너로 SpringRunner를 사용하기 위해서는 테스트 클래스에 @RunWith(SpringRunner.class)를 추가해야 한다.
JUnit 5에서는 @ExtendWith(SpringExtention.class)를 대신 적용하면 된다.
하지만 스프링 부트 2.1 버전부터 사용하는 JUnit의 버전이 5.x로 변경되었고, 해당 어노테이션이 @SpringBootTest에 포함되도록 변경되었기 때문에 스프링 부트 2.1 버전부터 @SpringBootTest 추가시 @ExtendWith(SpringExtention.class)를 생략할 수 있다.
@SpringBootTest, 또는 @WebMvcTest와 같은 어노테이션과 함께 사용하면 ApplicationContext 설정 측면에서 편해진다.
@SpringBootTest
스프링 프로젝트에 대한 통합 테스트를 진행할 때 @SpringBootTest 어노테이션을 테스트 클래스에 적용한다.
해당 어노테이션에 따로 옵션을 주지 않은 경우, 스프링 프로젝트를 구동하는 데 필요한 모든 빈을 ApplicationContext에 추가하는 역할을 한다.
스프링 부트 프로젝트 구성에 의해, @SpringBootApplication이 적용된 메인 클래스를 기준으로 모든 빈들을(@Component가 적용된 빈: @Controller, @Service, @Repository, @Configuration 등) ApplicationContext에 추가하게 된다.
이러한 특징으로 실제 배포 환경과 가장 유사하게 테스트가 가능하다는 장점이 있지만, 속도가 느리고 디버깅이 어렵다는 단점이 존재한다.
@WebMvcTest
이 어노테이션은 컨트롤러에 해당하는 컴포넌트만 스캔하는 역할을 한다.
(ApplicationContext에 들어갈 수 있는 모든 빈들을 가져오지 않는다)
그래서 웹 요청에 대한 응답만 간단히 테스트할 때 사용된다.
@WebMvcTest(원하는_컨트롤러.class)의 형식으로 테스트 클래스에 적용한다.
또한, @WebMvcTest를 적용하면 MockMvc(서버에 배포하지 않고 요청/응답 테스트 가능한 모의 객체 클래스)가 컨텍스트에 등록되므로 의존 자동 주입을 통해 MockMvc를 사용할 수 있다.
웹 관련 빈만 컨텍스트에 추가하기 때문에 속도가 빠르다는 장점이 있으나, 단위 테스트 환경에서는 실제 Service나 Repository 대신 Mock 객체를 사용하기 때문에 실제 환경과는 다른 오류가 발생할 수 있다고 한다.
@SpringBootTest와 같은 이유로, 스프링부트 2.1 버전부터 @ExtendWith(SpringExtension.class)를 생략할 수 있다.
참고한 자료
https://it-techtree.tistory.com/entry/How-to-write-java-test-code-using-junit
https://stackoverflow.com/questions/58901288/springrunner-vs-springboottest
https://spring.io/guides/gs/testing-web
https://findmypiece.tistory.com/173
'백엔드 공부 메모 > 테스트 코드' 카테고리의 다른 글
AssertJ 간단 정리 (0) | 2024.03.30 |
---|---|
스프링 컨트롤러 단위 테스트 - MockMvc 클래스 소개, 작동 원리 (2) | 2024.03.27 |
JUnit 간단 소개, JUnit 4 사용 예시 (0) | 2024.03.23 |