[Spring] Junit5 를 이용한 애플리케이션 테스트

김의진·2021년 12월 14일
0

더 자바, 애플리케이션을 테스트하는 다양한 방법(인프런) - 백기선님의 강의를 참고하여 작성하였습니다.

1. Junit 5

  • 자바 개발자가 가장 많이 사용하는 테스트 프레임워크
  • Java 8 이상을 필요로 함
  • Spring 2.2 이상부터는 Junit5 기본으로 탑재

2. 테스트의 필요성

  • 실무에서 개발을 진행하면서 테스트 코드 작성의 중요성을 느끼게 되었다. 개발 초기 단계에서는 개발과정에서 생길 수 있는 여러 예외, 에러상황에 대해서 테스트 코드 작성과정을 통해서 사전에 예측하고 개발과정에서는 검증을 할 수 있다. 개발과정동안 코드는 계속해서 수정되고 리팩토링 된다. 이 과정에서 기존 예측한 값들이 의도하지 않게 변경되는 것을 테스트과정에서 검증해준다. '완벽한 코드는 없다'는 말처럼 개발 이후에도 코드는 계속해서 변경되고 수정된다. 이 과정에서 미리 작성해둔 테스트코드는 우리가 원할때마다, 혹은 컴파일 시점마다 해당 코드의 정합성을 검증해준다.

  • 실서비스 되는 서비스에서 특정 에러가 발생했을 경우 해당 에러는 재현하는 절차는 생각보다 복잡하고 까다로우며 무엇보다 귀찮다. 개발자는 필요한 부분만을 가져와 간단하게 동작하는 테스트코드를 작성할 수 있고 이는 이슈사항을 빠르게 처리하고 생산성이 향상되는 결과로 이어지게 된다.

  • 개발단계에서 개발자의 테스트코드에 의해서 조금 더 세밀하게 검증된 코드는 QA 차수를 줄이게 되고 이는 개발효율의 향상으로 이어지게 된다.

3. Junit 5 시작하기

  • @Test 를 명시함으로 해당 메서드가 테스트 메서드임을 나타냄.

  • @DisplayName 을 이용하여 해당 테스트 진행시 표기되는 이름을 정해줄 수 있음.

  • @BeforeAll 전체 메서드 시작전 한번만 실행

  • @BeforeEach 각 메서드 시작전 실행

  • @AfterAll 전체 메서드 종료후 한번만 실행

  • @AfterEach 각 메서드 종료후 실행

@BeforeAll, @AfterAll의 경우 해당 메서드를 Static으로 선언해줘야한다.

  • @Disabled 해당 어노테이션이 붙은 메서드는 테스트가 동작하지 않는다.
    좋은 방법은 아니다. (깨진 테스트는 빠르게 수정해두는게 좋다.)
class ServiceTest {
    @BeforeAll
    static void beforeAllTest() {
        System.out.println("beforeAll Test");
    }

    @BeforeEach
    void beforeEachTest() {
        System.out.println("beforeEach Test");
    }

    @Test
    void test() {
        System.out.println("test");
    }

    @AfterEach
    void afterEachTest() {
        System.out.println("afterEach test");
    }

    @AfterAll
    static void afterAllTest() {
        System.out.println("afterAll Test");
    }
}

Junit Main Annotation

  • @SpringBootTest
    통합 테스트 용도로 사용됨, @SpringBootApplication을 찾아가 하위의 모든 Bean을 스캔하여 로드한다.
    그 후 Test용 Application Context를 만들어 Bean을 추가하고, MockBean을 찾아 교체한다.

  • @ExtendWith
    JUnit4에서 @RunWith로 사용되던 어노테이션이 ExtendWith로 변경됨
    @ExtendWith는 메인으로 실행될 Class를 지정할 수 있음

  • @WebMvcTest(Class명.class)
    ()에 작성된 클래스만 실제로 로드하여 테스트를 진행

  • 매개변수를 지정해주지 않으면 @Controller, @RestController, @RestControllerAdvice 등 컨트롤러와 연관된 Bean이 모두 로드됨

4. Assertion

Junit5 에서는 굉장히 다양한 테스트 메서드를 지원해준다. 그 중 몇개의 내용만 정리 해둔다.

  • assertNotNull() - Null이 아니여야함.

  • assertEquals(A, B, message) - A, B의 인자값이 같아야함.
    assertEquals의 인자값으로 들어가는 message는 람다식의 Supplier를 이용하게 되면 해당 메시지가 호출되는 시점에만 작동되기 때문에 문자열 연산에서 성능 이점을 가져올 수 있다.

  • assertTrue() - 해당 인자의 조건이 참이어야 한다.

  • assertAll() - 해당 인자값으로 포함되어 있는 테스트를 모두 실행하게 된다.
    각각의 테스트메서드는 전의 테스트가 한개라도 실패하면 뒤에 있는 테스트는 모두 진행되지 않게 된다.
    앞의 테스트가 통과하고 난 후에 뒤에 있는 테스트가 진행되기때문에 여러개의 테스트 실패를 한번에 확인하기 어렵다.
    이럴때 assertAll 을 이용할 경우 앞의 테스트 성공 유무에 상관없이 모든 테스트가 진행되게 된다.

  • assertTimeout() - 특정 시간이 넘어갈 경우 실패 하게 된다.

5. 조건에 따른 테스트

  • @EnabledOnJre - Jre 버전에 따른 분기 지원
  • @EnabledOnOs - Os에 따른 분기 지원
  • @assumeTrue() - 인자로 전달 받은 값이 true면 테스틀 진행하고, 그렇지 않으면 테스트를 생략한다.

6. 태깅과 필터링

  • 태킹이란 테스트들을 그룹화 할 수 있는 기능이다.
    ex) 오래걸리는 테스트, 단위테스트, 통합테스트 끼리 묶어서 테스트할 수 있음

  • @Tag를 사용하여 각 테스트끼리 묶을 수 있다.
    테스트 시점에 특정 태그만 동작시키고 싶을때는 인텔리제이, 메이븐 설정을 통해 가능하다.

7. Junit5 테스트 인스턴스

  • Junit에서 각각의 테스트들은 하나의 클래스에 속해있더라도 실행시점에서는 각 테스트마다 별도의 인스턴스가 생성되어 실행된다.
    예를 들어 아래와 같이 A, B 테스트 메서드를 담은 클래스는 각각의 테스트가 실행 될 때마다 새로운 인스턴스를 만들어 각각의 메서드를 실행시키게 된다.
class ServiceTest {
    @Test
    void A() {
        System.out.println("A");
    }

    @Test
    void B() {
        System.out.println("B");
    }
}

각각의 테스트는 코드는 순서대로 동작하지 않으며 어떤 테스트 메서드가 우선 실행될지는 알 수 없다.

profile
3년차 Spring, Java 주니어 백엔드 개발자입니다.

0개의 댓글

관련 채용 정보