부트캠프

Spring MVC - Testing part 1

hunm719 2023. 3. 6. 19:56
1.단위 테스트(Unit Test)

 -일반적인 테스트의 의미
  ● 테스트는 어떤 대상에 대한 일정 기준을 정해놓고, 그 대상이 정해진 기준에 부합하는지 부합하지 못하는지를 검증하는 과정
   테스트를 제대로 잘 거쳐서 테스트 대상이 검증 과정에 잘 통과하게 만들어 최대한 더 나은 결과를 얻기 위해 테스트를 진행함
 
 -단위 테스트(Unit Test)

애플리케이션의 일반적인 테스트 분류


   기능 테스트
   ○ 주로 애플리케이션을 사용하는 사용자 입장에서 애플리케이션이 제공하는 기능이 올바르게 동작하는지를 테스트함
    우리가 개발한 애플리케이션과 연관된 대상(API툴, DB 등)이 많기 때문에 흔히 이야기하는 단위 테스트로 부르기는 힘듦

   통합 테스트
    클라이언트 측 툴 없이 개발자가 짜 놓은 테스트 코드를 실행시켜서 이루어지는 경우가 많음
    통합 테스트 역시 애플리케이션의 여러 계층이 연관되어 있어 단위 테스트라고 하기에는 그 범위가 여전히 큼

   슬라이스 테스트
    애플리케이션을 특정 계층으로 쪼개어서 하는 테스트
    슬라이스 테스트 역시 HTTP 요청이 필요하고, 데이터 액세스 계층의 경우 DB와 연동되어 있기 때문에 단위 테스트라고 부르기엔 단위가 큼
    애플리케이션의 일부만 테스트하기 때문에 부분 통합 테스트라고도 부름

   단위 테스트
    일반적으로 비즈니스 로직에서 사용하는 클래스들이 독립적으로 테스트하기 가장 좋은 대상이기 때문에 단위 테스트라고 부르는 경우가 많음
    만든 기능이 기대한 대로 빠르게 동작하는지 테스트하기 위해 대부분 메서드 단위로 작성됨
    데이터베이스가 연동된다고 해도 테스트 이 전과 이 후의 데이터베이스 상태가 동일하게 유지될 수 있다면 단위 테스트에 포함 될 수는 있음
   


 -단위 테스트를 위한 FIRST 원칙
 (1)Fast : 일반적으로 작성한 테스트 케이스는 빨라야 한다는 의미
 (2)Independent : 각각의 테스트 케이스는 독립적이어야 한다는 의미
 (3)Repeatable : 테스트 케이스는 어떤 환경에서도 반복해서 실행이 가능해야 된다는 의미
 (4)Self-validating : 단위 테스트는 성공 또는 실패라는 자체 검증 결과를 보여주어야 한다는 의미
 (5)Timely : 단위 테스트는 테스트 하려는 기능 구현을 하기 직전에 작성해야 한다는 의미

 


 +Given-When-Then구조
  ● Given : 테스트할 상황을 설정함. 테스트할 객체나 변수를 초기화하고, 입력값을 설정하거나, 의존성을 주입하는 등의 작업을 수행함
  ● When : 테스트할 작업을 수행함. 테스트할 코드를 실행하고, 예상 결과를 얻음
  ● Then : 예상된 결과를 검증함. 실행 결과를 검사하여, 예상한 값과 일치하는지 확인함

 


 +어써션(Assertion)
  ● 테스트 결과를 검증할 때 주로 사용함
  ● 테스트 케이스의 결과(예상하는 결과 값)가 반드시 참(true)이어야 한다는 것을 논리적으로 표현한 것


2.JUnit을 사용한 단위 테스트

 -Spring Boot Initializr에서 Gradle 기반의 Spring Boot 프로젝트를 생성하고 오픈하면 기본적으로 ‘src/test’ 디렉토리가 만들어지고 JUnit이 포함되어 있음
 
 -JUnit을 사용한 테스트 케이스의 기본 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.junit.jupiter.api.Test;
 
public class JunitDefaultStructure {
 
    @Test
    public void test1() {
        // 테스트 하고자 하는 대상에 대한 테스트 로직 작성
    }
 
    @Test
    public void test2() {
        // 테스트 하고자 하는 대상에 대한 테스트 로직 작성
    }
 
    @Test
    public void test3() {
        // 테스트 하고자 하는 대상에 대한 테스트 로직 작성
    }
}
cs



 -Assertion 메서드

  ● assertEquals() : 기대하는 값과 실제 결과 값이 같은지를 검증

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
 
public class HelloJUnitTest {
    @DisplayName("Hello JUnit Test")
    @Test
    public void assertionTest() {
        String expected = "Hello, JUnit";
        String actual = "Hello, JUnit";
 
        assertEquals(expected, actual);
    }
}
cs


  ● assertNotNull() : 테스트 대상 객체가 null 이 아닌지를 검증

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.codestates.CryptoCurrency;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
 
import static org.junit.jupiter.api.Assertions.assertNotNull;
 
public class AssertionNotNullTest {
 
    @DisplayName("AssertionNull() Test")
    @Test
    public void assertNotNullTest() {
        String currencyName = getCryptoCurrency("ETH");
 
        assertNotNull(currencyName, "should be not null");
    }
 
    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit);
    }
}
cs


  ● assertThrows() : 호출한 메서드의 동작 과정 중에 예외가 발생하는지 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
 
import static org.junit.jupiter.api.Assertions.*;
 
public class CryptoCurrency {
    public static Map<StringString> map = new HashMap<>();
 
    static {
        map.put("BTC""Bitcoin");
        map.put("ETH""Ethereum");
        map.put("ADA""ADA");
        map.put("POT""Polkadot");
    }
}
 
public class AssertionExceptionTest {
 
    @DisplayName("throws NullPointerException when map.get()")
    @Test
    public void assertionThrowExceptionTest() {
 
        assertThrows(NullPointerException.class, () -> getCryptoCurrency("XRP"));
    }
 
    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit).toUpperCase();
    }
}
cs



 -JUnit 프레임워크에서 제공하는 애너테이션
  ● @BeforeEach

   ○ 각각의 테스트 메서드가 실행되기 전에 실행되는 메서드를 정의함.

   ○ 테스트 메서드에서 공통으로 사용되는 객체를 초기화하거나, 데이터를 설정하는 등의 작업을 수행함


  ● @BeforeAll

   ○ 모든 테스트 메서드가 실행되기 전에 딱 한번만 실행되는 메서드를 정의함

   ○ 애플리케이션의 환경 설정, 데이터베이스 연결 등과 같은 초기화 작업을 수행함

 

  ● @AfterEach

   ○ 각각의 테스트 메서드가 실행된 후에 실행되는 메서드를 정의함

   ○ 테스트에서 사용한 객체를 해제하거나, 데이터를 초기화하는 등의 작업을 수행함


  ● @AfterAll

   ○ 모든 테스트 메서드가 실행된 후에 딱 한번만 실행되는 메서드를 정의함

   ○ 테스트 후에 애플리케이션을 종료하거나, 데이터를 초기화하는 등의 작업을 수행함

 

 +@BeforeAll과 @AfterAll은 static 메서드로 정의해야 하며, 다른 메서드와는 다르게 인스턴스 생성 없이 실행됨.

 

 

 

 

 

 

 

 

 

-이미지 및 내용 출처 : code states

'부트캠프' 카테고리의 다른 글

Spring MVC - Testing part 3  (0) 2023.03.09
Spring MVC - Testing part 2  (0) 2023.03.08
Spring MVC - 트랜잭션  (0) 2023.03.03
Spring MVC - JPA 기반 데이터 액세스 계층 part 2  (0) 2023.03.01
HTTP 헤더(Header)  (0) 2023.02.24