[Junit] @BeforeEach, @BeforeAll, @AfterEach, @AfterAll에 대해 알아보자
토비의 스프링 스터디를 진행하며 2장에서 더 알아보고 싶은 내용으로 위와 같은 주제를 정했다.
이제부터 자세히 알아보자!
1. 기본적인 소개
픽스쳐(fixture)
- 테스트를 수행하는 데 필요한 정보나 오브젝트를 픽스처라고한다.
@BeforeAll == @BeforeClass
- 테스트 클래스에 있는 어떤 테스트를 처음 실행하기 전 한 번만 실행된다.
- static으로 만들어져야 하며 리턴타입은 void이어야 함
@BeforeEach == @Before
- 현재 클래스의 각 @Test, @RepeatedTest, @ParameterizedTest 또는 @TestFactory 메소드보다 먼저 메소드가 실행되어야 함을 의미
- 비즈니스 로직이 복잡해지고 테스트에 여러 초기화가 필요하다면 여러 개의 @BeforeEach 메소드를 만들 수 있다.
- 다만 초기화 메소드들 사이의 실행 순서는 보장되지 않으니 순서가 필요한 경우에는 @Order 어노테이션을 사용해 순서를 지정해준다.
@AfterAll == @AfterClass
- 테스트 클래스에 있는 테스트를 모두 실행하고 그 후에 한 번만 실행된다.
- static으로 만들어져야 하며 리턴타입은 void이어야 함
@AfterEach == @After
- 현재 클래스의 각 @Test, @RepeatedTest, @ParameterizedTest 또는 @TestFactory 메소드 이후에 메소드가 실행되어야 함을 의미
- 테스트가 실패해도 수행됨
테스트 코드에서 중복된 코드들을 줄이기위해 사용되는 어노테이션!
보통은 테스트 수준의 초기화(@BeforeEach, @AfterEach)면 충분하다!
2. 내부 구현
annotationTest.java
LifecycleMethodUtils.java
TestMethodTestDescriptor.java
3. 실제 오픈소스 사례
스프링 프레임워크 코어
@BeforeEach public void setUp() throws Exception { this.webRequest = new ServletWebRequest(new MockHttpServletRequest()); this.attributeStore = new DefaultSessionAttributeStore(); this.attributeHandler = new SessionAttributesHandler(TestController.class, this.attributeStore); this.controller = new TestController(); this.mavContainer = new ModelAndViewContainer(); }
라인 아르메리아 (Java 8 및 Netty 상에 비동기 RPC/API 클라이언트-서버를 구현한 것 - 라인 메신져에서 사용됨)
@BeforeEach void setUp() { when(eventLoop.inEventLoop()).thenReturn(true); doAnswer((Answer<Void>) invocation -> { invocation.<Runnable>getArgument(0).run(); return null; }).when(eventLoop).execute(any()); ctx = ServiceRequestContext.builder(HttpRequest.of(HttpMethod.GET, "/")) .eventLoop(eventLoop) .build(); }
네이버 spring-jdbc-plus
@BeforeEach public void setUp() { this.context.setForceQuote(false); this.sqlGenerator = createSqlGenerator(DummyEntity.class); }
4. 잘 활용해보기
@BeforeEach를 사용해 전역으로 사용하는 객체를 초기화하는 경우의 문제점
1) 어떤 상황일 경우에 이 기대값이 나오는지를 한 눈에 알 수가 없다.- setup() 메소드를 다 확인해보아야 한다
- 객체가 어떤 값을 가지고 있는지
- 어떤 함수가 어떻게 mock/stub 처리 되었는지
- @BeforeEach 하나만 변경해도 모든 메소드가 영향을 받는다.
해결방법
- 클래스 내부에 private 팩토리 메소드를 만들어 사용
- 클래스 외부에 static 팩토리 메소드를 만들어서 사용
얻을 수 있는 장점
- 전체 테스트 코드의 양이 줄어들고, 재사용성이 좋다
- 각각의 테스트 메소드의 가독성이 좋아지고, 맥락 파악이 쉬워진다.
- 각각의 테스트 픽스처가 모두 1회성으로 끝나는 지역변수를 사용하기 때문에 테스트간 결합도가 낮아진다
추가로 알아볼 점) @BeforeAll이 @BeforeEach보다 더 메모리를 많이 먹는다?
참고링크
[자바와 JUnit을 활용한 실용주의 단위 테스트]
https://junit.org/junit5/docs/current/user-guide/
https://jojoldu.tistory.com/611
https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java
https://github.com/line/armeria/blob/master/core/src/test/java/com/linecorp/armeria/client/BlockingWebClientTest.java
https://github.com/naver/spring-jdbc-plus/blob/master/spring-data-jdbc-plus-sql/src/test/java/com/navercorp/spring/data/jdbc/plus/sql/convert/SqlGeneratorEmbeddedTest.java
Author And Source
이 문제에 관하여([Junit] @BeforeEach, @BeforeAll, @AfterEach, @AfterAll에 대해 알아보자), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ak2j38/Junit-BeforeEach-BeforeAll-AfterEach-AfterAll를-알아보자저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)