ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TC(Test Case) & JUnit
    STUDY/백엔드 2020. 12. 18. 17:45

    JUnit

    • Java에서 독립된 단위 테스트(Unit Test)를 지원해주는 프레임워크이다.
    • 특징
      1. @Test 메서드를 호출할 때 마다 새로운 인스턴스를 생성하여 독립적인 테스트가 이루어진다.
      2. Test마다 경과 시간이 나오기 때문에 최적화된 코드를 유추할 수 있다.
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-params</artifactId>
        <version>5.4.2</version>
        <scope>test</scope>
    </dependency>
    • 지원하는 Annotation
      1. @Test - 테스트를 실행하는 메소드로 선언 JUnit은 각각의 테스트가 서로 영향을 주지 않고 독립적으로 실행되며 @Test마다 개체를 생성해서 내부적으로 실행된다.
      2. @Disabled / @Ignore - 테스트를 실행하지 않는 메소드로 선언
      3. @BeforeEach / @Before - @Test 메소드가 실행되기 전에 실행된다. 주로, 공통으로 사용하는 부분을 선언한다.
      4. @AfterEach / @After - @Test 메소드가 실행된 후에 실행된다. 주로, 테스트시 사용한 자원을 해제할 때 사용한다.
      5. @BeforeAll / @BeforeClass - @Test 메소드보다 먼저 한 번만 수행되어야 할 경우에 사용한다.
      6. @AfterAll / @AfterClass - @Test 메소드보다 나중에 한 번만 수행해야할 때 사용한다.
    *실행 코드

    @BeforeEach
    void beforeEach(){ System.out.println("@BeforeEach 수행");}

    @BeforeAll 
    void beforeAll(){ System.out.println("@BeforeAll 수행");}

    @AfterEach
    void afterEach(){ System.out.println("@AfterEach 수행");}

    @AfterAll 
    void afterAll(){ System.out.println("@AfterAll 수행");}

    @Test
    void beforeAndAfterTest(){ System.out.println("before and after test");}

    @Test
    void printHelloWorld() throws Exception {
        String word = "Hello World";

        mockMvc.perform(get("/"))
                    .andExpect(status().isOk())
                    .andExpect(content().string(word))
                    .andDo(print());
    }

    *결과*

    @BeforeAll 수행
    @BeforeEach 수행
    printHelloWorld() 수행   // 실제 controller method
    @AfterEach 수행
    @BeforeEach 수행
    beforeAndAfterTest()
    @AfterEach 수행
    @AfterAll 수행

    • Test Code가 중요한 이유 : Test code 자체가 Documentation이다.
      1. API 사용법에 대한 기술
      2. 하나의 예제가 되어준다.
      3. 어떤 데이터가 in, out 되는지 확인할 수 있다.
      4. 해당 함수에서 어떠한 결과들이 나오는지 모두 확인할 수 있다.
    • 참고

    • Constructor Test : 단순한 로직의 경우 굳이 테스트하지 않는다. 단 값을 초기화하거나 Load하는 경우가 있을 때는 테스트를 수행한다.

     

    • Getter / Setter Test : 단순한 Getter / Setter는 굳이 테스트하지 않는다. 로직이 있는 경우에는 로직을 별도의 메소드로 분리하고 이를 테스트하는 것이 좋다.

     

    • Boundary Test : Null에 대한 확인, Default 값에 대한 확인, 범위가 있는 경우 MIN/MAX 값에 대한 확인을 목적으로 한다. 이 경우엔 결국 NullPointerException이 발생하지 않도록 방어 혹은 검증 로직을 보완하는 것이 바람직하다.

     

    • Exception Test : 예측한 예외가 실제로 발생하는지 확인한다. try/catch문이 아닌 단순 어노테이션 설정만으로 간단하게 확인할 수 있다.
    더보기

    @Test (expected = NullPointerException.class)

    public void testException() {

        throw new NullPointerException();

    }

    • Equality Test - value와 reference 비교
    더보기

    @Test

    public void testReferenceEqual() {

     

        String str1 = new String("someValue");

        String str2 = str1;

       

        assertEquals("same value", str1, str2);

        assertSame("same reference", str1, string2);

     

    }

    • Equality Test - 숫자값 비교
    더보기

    @Test

    public void testDoubleEqual() {

     

        double num1= 10 / 6;

        double num2 = 1.66666;

     

         assertEquals("소수 다섯번째까지 같음", num1, num2, 5);

     

    }

    • Equality Test - 리스트/배열의 비교
    더보기

    @Test

    public void testListEqual() {

     

        List list1 = Arrays.asList("a", "b", "c");

        List list2 = Arrays.asList("a", "b", "c");

     

        assertEquals("리스트의 값과 순서가 같음", list1, list2);

     

    }

     

    @Test

    publicvoidtestArrayEqual(){

     

        String[]arr1=newString[]{"a","b","c"};

        String[]arr2=newString[]{"a","b","c"};

     

        assertArrayEquals("배열의 값과 순서가 같음", arr1, arr2);

     

    }

    • Equality Test - Value Object의 비교
    더보기

    @Test

    public void testObjectEqual() {

     

        UserVo user1 = new UserVo(25, "gildong", "hi");

        UserVo user2 = new UserVo(25, "gildong", "hi");

     

        assertEquals(user1.getAge(), user2.getAge());

        assertEquals(user1.getName(), user2.getName());

        assertEquals(user1.getDescription(), user2.getDescription());

     

    }

     

    • Parameterized Test : parameter 값만 바꿔가면서 동일한 테스트를 반복해서 수행하고 싶을 때 유용하다.

     

    • Timeout Test : 테스트에 걸리는 시간을 지정해서, 해당 시간을 넘길 경우 Fail 처리를 할 수 있다.
    더보기

    @Test (timeout = 1)

    public void testTimeout() { }

    • Test Ignore : 테스트를 안하고 싶을 때 사용한다. 클래스와 메소드 단위 모두 사용 가능하다.
    더보기

    @Ignore ("클래스 단위로 테스트를 수행하지 않도록 설정(실제론 상세 원인을 표시)")

    public class IgnoreTest {

        @Test

        public void testIgnored() {

            assertTrue("모든 테스트 메소드는 실행이 되지 않음", true);

        }

    }

     

    @Ignore ("메소드 단위로 테스트 수행하지 않도록 설정(실제론 상세 원인을 표시)")

    @Test

    public void testIgnore() {

         assertTrue("이 테스트 메소드는 실행이 되지 않음", true);

    }


     

    1. 통합 테스트 - @SpringBootTest

    모든 빈을 등록하여 테스트를 진행한다. 그렇기 때문에 애플리케이션 규모가 크면 테스트가 많이 느려진다.

    • @RunWith : 해당 어노테이션을 사용하면 JUnit의 러너를 사용하는게 아니라 지정된 SpringRunner 클래스를 사용한다.
    • @SpringBootTest
    • @EnableConfigurationProperties : Configuration으로 사용하는 클래스를 빈으로 등록할 수 있게 해줌.
    •   ( Enable support for {@link ConfigurationProperties} annotated beans. )

     

    2. 컨트롤러 테스트 - @WebMvcTest

    - 웹상에서 요청과 응답에 대한 테스트를 할 수 있다. 해당 어노테이션을 사용하면, @Controller, @ControllerAdvice, @JsonComponent와 Filter, WebMvcConfiguer, HandlerMethodArgumentResolver만 로드되기 때문에 전체 테스트보다는 가볍다.

     

    3. JPA 관련 테스트 - @DataJpaTest

    - JPA 관련된 설정만 로드한다. 그렇기 때문에 @Entity 클래스를 스캔하여 스프링 데이터 JPA 저장소를 구성한다. 기본적으로 인메모리 데이터베이스를 이용함. 데이터소스의 설정이 정상적인지, JPA를 사용하서 데이터를 제대로 생성, 수정, 삭제하는지 등의 테스트가 가능함.

    • @AutoConfigureTestDataBase : 데이터 소스를 어떤 걸로 사용할지에 대한 설정
      • Replace.Any : 기본적으로 내장된 데이터소스를 사용
      • Replace.NONE : @ActiveProfiles 기준으로 프로파일이 설정됨
    • @DataJpaTest : 테스트가 끝날 때마다 자동으로 테스트에 사용한 데이터를 롤백

     

    4. REST 관련 테스트 - @RestClientTest

    - Rest 통신의 JSON 형식이 예상대로 응답을 반환하는지 등을 테스트 함

    • @RestClientTest : 테스트 대상이 되는 빈을 주입받음
    • @Rule
    • MockRestServiceServer : 클라이언트와 서버 사이의 REST 테스트를 위한 객체. 내부에서 RestTemplate을 바인딩하여 실제로 통신이 이루어지게끔 구성할 수 있음. 

     

    5. Json의 직렬화, 역직렬화 테스트 - @JsonTest

    - Gson, Jackson의 테스트를 제공함.

     

    6. JUnit5에 추가된 내용

    • @DisplayName : method 명으로 표현하기 부족했다면 해당 어노테이션을 유용하게 사용할 수 있다.
    • Lifecycle Method 
      • @BeforeClass, @AfterClass -> @BeforeAll, @AfterAll
      • @Before, @After -> @BeforeEache, @AfterEach
    • 중첩된 테스트 클래스 - @Nested

     

    7. 참고

    'STUDY > 백엔드' 카테고리의 다른 글

    Bean  (0) 2021.01.05
    Mybatis  (0) 2020.12.31
    Server Log  (0) 2020.12.28
    Apache Spring boot(내부 tomcat) 연동  (0) 2020.12.24
    WEB 서버와 WAS  (0) 2020.12.17
Designed by Tistory.