JUnit의 동작과정과 Test환경에서 Context관리시 주의할 점

LinkinPark·2024년 9월 16일

개요

평소 테스트를 작성할 때, @Test만 붙여서 사용하고, 정작 어떻게 scan하고 동작하는지 모르는 상태인 것을 인지했다.

AS IS - @Test 를 메서드에 붙였을 때 어떻게 스캔하고 동작하는지 모른다.
TO BE - @Test 어노테이션을 붙였을 때 프레임워크의 동작과정과 스캔 과정을 이해하고 사용한다.

JUnit동작 과정

  1. 테스트 실행 요청
    테스트 실행은 JUnit runner 또는 Test suite를 통해 요청된다.
    Junit4에서는 JUnitCore 클래스를 사용하고, Junit5에서는 JunitPlatform과 TestEngine을 사용하여 테스트를 실행한다.

  2. 테스트 클래스 로딩
    JUnit은 테스트 클래스의 메타데이터를 읽고, 해당 클래스의 테스트 메서드를 식별한다.
    @Test 어노테이션이 붙은 메서드를 찾는다.

JUnit5에서는 TestEngine 인터페이스를 구현한 엔진이 사용되며, @Test어노테이션과 @ExtendWith어노테이션을 통해 메타데이터를 수집한다.

  1. 테스트 준비
  • JUnit4 : TestClass는 @Before@After어노테이션이 붙은 메서드를 호출하여 테스트 준비를 한다. @BeforeClass@AfterClass는 클래스 로딩 시 한 번만 호출된다.
  • JUnit5 : @BeforeEach, @AfterEach, @BeforeAll, @AfterAll 어노테이션이 붙은 메서드를 호출하여 테스트 준비를 한다. @BeforeAll, @AfterAll은 로딩 시 한 번만 호출된다.
  1. 테스트 실행
  • 테스트 메서드는 JUnit의 TestRunner에 의해 실행된다. JUnit 4에서는 BlockJUnit4ClassRunner가 기본적인 runner 역할을 하고, JUnit 5에서는 TestEngine이 테스트를 실행한다.
  • JUnit 4: 각 테스트 메서드는 매 번 새로운 인스턴스의 테스트 클래스에서 실행된다. @Before 메서드는 각 테스트 메서드 실행 전에 호출된다.
  • JUnit 5: 테스트 메서드는 TestEngine에 의해 실행되며, @BeforeEach, @AfterEach 메서드가 각 테스트 전에 호출된다.
  1. 테스트 후처리
    테스트 실행 후 JUnit은 테스트 결과를 수집한다. 성공/실패/오류 등

  2. 결과 보고

  • JUnit은 테스트 실행 결과를 테스트 리포트 형태로 제공한다. 이는 성공, 실패, 오류 등의 정보를 포함한다.
  • JUnit 4: JUnitCore가 콘솔에 테스트 결과를 출력한다.(GUI도 있다)
  • JUnit 5: TestEngineTestExecutionListener를 통해 결과를 수집하고, 이를 다양한 리포트 포맷으로 출력한다.(console, xml, html 등) 물론 default는 console이다.

JUnit과 함께 동작하는 프레임워크 및 라이브러리

  1. JUnit(Jupiter API)
    JUnit4에서는 별도의 JUnit Core 라이브러리를 사용했으나, 5부터는 Jupiter가 테스트 실행의 핵심 역할을 한다.

  2. Hamcrest
    보다 읽기 쉬운 assertion을 제공한다.

  3. Mockito
    의존성 있는 객체를 모킹하기 위해 사용되는 라이브러리이다.
    실제 객체를 생성하지 않고도 테스트가 가능해진다.

  4. Spring Test
    Spring Framework기반 프로젝트라면 해당 spring-test 라이브러리를 통해 Spring 기능 테스트가 가능하다.

테스트 환경에서 빈의 주입

@ContextConfiguration

해당 어노테이션을 사용하면, 테스트 환경에서 필요한 Spring 설정 파일을 로드할 수 있다.
xml을 로드하고 싶다면 해당 파일의 위치를 location 속성에 작성하면된다.

주의점

보통 Context는 재사용하도록 설계되어있다.
즉, 여러 클래스나 메서드가 존재하더라도 기존에 생성된 Spring Context를 사용한다.

만약 해당 컨텍스트를 분리하고 싶다면, @DirtiesContext 어노테이션을 사용해 테스트별로 새로운 컨텍스트가 생성되게 하거나, @ContextConfiguration 어노테이션을 통해 원하는 빈만 따로 사용할 수 있다.

여기서 ContextConfiguration은 의존되는 빈들이 한 곳에 존재한다면 A만 설정해도 A랑 의존된 B,C도 함께 자동으로 불러와진다.
하지만 A가 의존하는 B,C 빈이 다른 설정파일이나 패키지에 존재한다면, B,C도 ContextConfiguration에 명시해주어야한다.

@RunWith for JUnit4

테스트 실행 방식을 설정하는데 사용된다.

  • 테스트 실행 방식 제어
    - @RunWith를 통해 테스트를 실행하는 방식이나 환경을 커스터마이즈할 수 있다. 예를 들어, 특정 프레임워크나 라이브러리와 통합하기 위해 런너를 사용한다.
  • Runner
    - runner는 JUnit가 테스트를 실행하는 방식을 정의하는 클래스이다. 기본적으로 JUnit은 BlockJUnit4ClassRunner를 사용하지만, @RunWith를 통해 다른 runner를 지정할 수 있다.

@ExtendWith for JUnit5

RunWith와 비슷한 역할을 하지만, 살짝 다르다.
보통은 RunWith와 비슷한 역할인 Spring TestContext Framework와 통합해서 테스트하기위해 사용된다. Spring Context에 테스트를 주입한다.
Mockito Framework와 통합할 수도 있고 DB관련 테스트에도 사용할 수 있다.

  • 테스트 확장
    - @ExtendWith테스트 확장(extensions)을 테스트 클래스 또는 테스트 메서드에 적용할 수 있게 해준다. 테스트 확장은 테스트의 실행 방식을 변경하거나, 추가적인 기능을 제공하는 컴포넌트다.
  • 테스트 환경 설정
    • @ExtendWith를 사용하여 테스트 실행 전후에 환경 설정이나 자원 관리를 하는 확장 기능을 추가할 수 있다.
  • 커스터마이즈 동작 추가
    • 테스트의 실행 흐름을 변경하거나, 테스트 메서드에 매개변수를 주입하는 등의 작업을할 수 있다.
profile
It's work, but touch it

0개의 댓글