Java & Spring / / 2023. 5. 19. 17:56

[Java Test] 1. JUnit5 (3) 테스트 인스턴스 & 순서 지정

728x90

 

 

 

Contents

     

     

     

    JUnit은 기본 전략으로 테스트 메소드마다 테스트 인스턴스를 새로 만든다. 테스트 메소드를 독립적으로 실행해서 예상하지 못한 부작용을 방지하기 위한 전략이다.

     

    1. 기본 전략  : 메소드마다 인스턴스 생성

    예를 들어, 전역변수를 생성해서 각 메소드에서 값을 변화해도, 초기값으로 계속 남아있다.

    각 메소드에서 this를 출력해보면 객체가 다른 것도 확인이 가능하다.

    public class InstanceTest {
    
        int value = 1;
    
        @Test
        void check_instance1(){
            System.out.println("1 : " + this.toString() +", value : " + (value++));
        }
    
        @Test
        void check_instance2(){
            System.out.println("2 : " + this.toString() +", value : " + (value++));
        }
    }

    테스트 간의 의존성을 없애기 위해서이며, 테스트 순서에 의해 인스턴스 값이 바뀌면 불안정해진다.

    테스트 순서는 예측을 할 수가 없다. (JUnit5부터는 선언되는 순으로 실행되기는 한다.)

    따라서 테스트간 의존성은 없애는 것이 좋다.

     

    2. @TestInstance(Lifecycle.PER_CLASS) : 클래스 1개당 인스턴스 생성

    - JUnit 5에서는 기본 전략을 변경할 수 있다.

      클래스에 @TestInstance(Lifecycle.PER_CLASS)를 붙이면 클래스당 인스턴스를 하나만 만들어 사용한다.

    -  클래스당 인스턴스를 하나만 만들면 @BeforeAll과 @AfterAll를 default 메소드로 정의할 수 있다. 즉, 꼭 static일 필요가 없다.

     

    테스트를 해보면

    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class InstanceTest {
    
        int value = 1;
    
        @Test
        void check_instance1(){
            System.out.println("1 : " + this.toString() +", value : " + (value++));
        }
    
        @Test
        void check_instance2(){
            System.out.println("2 : " + this.toString() +", value : " + (value++));
        }
    }

     

    클래스 인스턴스를 하나만 만들어서 value값이 증가한 것을 볼 수 있다.

    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class InstanceTest {
    
        int value = 1;
    
        @Test
        void check_instance1(){
            System.out.println("1 : " + this.toString() +", value : " + (value++));
        }
    
        @Test
        void check_instance2(){
            System.out.println("2 : " + this.toString() +", value : " + (value++));
        }
    
        @BeforeAll
        void beforeAll(){
            System.out.println("시작 시 한 번 실행");
        }
    
        @AfterAll
        void afterAll(){
            System.out.println("종료 시 한 번 실행");
        }
    }

    @BeforAll과 @AfterAll에 static을 적지 않아도 된다.

     

    3. @TestMethodOrder : 테스트 순서 지정  

    - JUnit5부터는 작성한 테스트 메소드 순서대로 실행되기는 하지만, 이에 의존해서는 안된다.

      테스트 인스턴스를 메소드마다 새로 만드는 것처럼 테스트 간의 의존성을 막기 위함인데, JUnit5 내부 로직 구성에 따라 언제든지 변경될 수 있다.

     

    - 하지만 종종 순서에 따라 테스트를 수행해야하는 경우가 있다. 

      예) 인수테스트, 특정 기능, 시나리오 테스트(회원가입, use 케이스 등)

      이 때 @TestMethodOrder를 사용하는데 @TestInstance(Lifecycle.PER_CLASS) 를 같이 사용하는 게 좋다. (필수x)

     

    @TestMethodOrder

    • Alphanumeric :
    • OrderAnnotation : 순서에 따라 실행 (org.junit.jupiter.api)
    • Random :
    // Order는 낮을 수록 우선순위가 높다.
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
    public class OrderTest {
    
        int value = 1;
    
        @Test
        @Order(3)
        void check_instance1(){
            System.out.println("1 : " + this.toString() +", value : " + (value++));
        }
    
        @Test
        @Order(1)
        void check_instance2(){
            System.out.println("2 : " + this.toString() +", value : " + (value++));
        }
    
        @Test
        @Order(2)
        void check_instance3() {
            System.out.println("3 : " + this.toString() + ", value : " + (value++));
        }
    
        @Test
        @Order(1)
        void check_instance4() {
            System.out.println("4 : " + this.toString() + ", value : " + (value++));
        }
    }

    우선순위가 같은 경우에는 무작위로 실행된다. (그래도 같은 숫자를 주지 말자)

     

     

    출처 : '더 자바, 애플리케이션을 테스트하는 다양한 방법'(백기선), 자료&11~12강

    300x250
    • 네이버 블로그 공유
    • 네이버 밴드 공유
    • 페이스북 공유
    • 카카오스토리 공유