Notice
Recent Posts
Recent Comments
«   2024/09   »
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
Archives
Today
Total
관리 메뉴

충분히 쌓여가는

테스트 코드 본문

Spring/Spring Boot

테스트 코드

빌드이너프 2023. 12. 20. 23:58

테스트 코드는 test 디렉터리에서 작업

 

given-when-then 패턴

테스트 코드를 세 단계로 구분해 작성하는 방식

given: 테스트 실행을 준비하는 단계

when: 테스트를 진행하는 단계

then: 테스트 결과를 검증하는 단계

 

@DisplayName("새로운 메뉴를 저장")
@Test
public void saveMenuTest() {
    // given: 메뉴를 저장하기 위한 준비 과정
    final String name = "아메리카노";
    final int price = 2000;
    
    final Menu americano = new Menu(name, price);
    
    // when: 실제로 메뉴를 저장
    final long savedId = menuService.save(americano);
    
    // then: 메뉴가 잘 추가되는지 검증
    final Menu savedMenu = menuService.findById(savedId).get();
    assertThat(savedMenu.getName().isEqualTo(name));
    assertThat(savedMenu.getPrice().isEqualTo(price));
}

 

Junit

자바 언어를 위한 단위 테스트 프레임워크

단위 테스트: 작성한 코드가 의도대로 작동하는지 작은 단위로 검증하는 것, 이때 단위는 보통 메서드가 됨

Junit을 사용하면 단위 테스트를 작성하고 테스트하는데 도움을 주고, 테스트 결과가 직관적인 장점

 

Junit은 테스트끼리 영향을 주지 않도록 각 테스트를 실행할 때마다 테스트를 위한 실행 객체를 만들고 테스트가 종료되면 실행 객체를 삭제한다

 

Junit 특징

테스트 방식을 구분할 수 있는 애너테이션을 제공

@Test 애너테이션으로 메서드를 호출할 때마다 인스턴스를 생성, 독립 테스트 가능

예상 결과를 검증하는 Assertion 메서드 제공

사용방법이 단순, 테스트 코드 작성 시간이 적음

자동 실행, 자체 결과를 확인하고 즉각적인 피드백을 제공

 

Junit에서 제공되는 검증 메서드인 assertEquals()로 a+b와 sum의 값이 같은지 확인

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class JUnitTest {
    @DisplayName("1+2는 3이다")
    @Test
    public void junitTest() {
        int a = 1;
        int b = 2;
        int sum = 3;

        Assertions.assertEquals(sum, a + b); // 값이 같은지 확인
    }
}

 

@DisplayName

테스트 이름을 명시

 

@Test

테스트를 수행하는 메서드가 됨


 

import org.junit.jupiter.api.*;

public class JUnitCycleTest {
    @BeforeAll // 전체 테스트를 시작하기 전에 1회 실행하므로 메서드는 static으로 선언
    static void beforeAll() {
        System.out.println("@BeforeAll");
    }

    @BeforeEach // 테스트 케이스를 시작하기 전마다 실행
    public void beforeEach() {
        System.out.println("@BeforeEach");
    }

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

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

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

    @AfterAll // 전체 테스트를 마치고 종료하기 전에 1회 실행하므로 메서드는 static으로 선언
    static void afterAll() {
        System.out.println("@AfterAll");
    }

    @AfterEach // 테스트 케이스를 종료하기 전마다 실행
    public void afterEach() {
        System.out.println("@AfterEach");
    }
}

// 실행결과
@BeforeAll
@BeforeEach
test1
@AfterEach
@BeforeEach
test2
@AfterEach
@BeforeEach
test3
@AfterEach
@AfterAll

@BeforeAll

전체 테스트를 시작하기 전에 처음으로 한 번만 실행됨

데이터베이스를 연결해야 하거나 테스트 환경을 초기화할 때 사용

전체 테스트 시행 주기에서 한 번 만 호출되어야 하기 때문에 메서드를 static으로 선언

 

@BeforeEach

테스트 케이스를 시작하기 전에 매번 실행

테스트 메서드에서 사용하는 객체를 초기화하거나 테스트에 필요한 값을 미리 넣을 때 사용

각 인스턴스에 대해 메서드를 호출해야 하므로 메서드는 static이 아니어야 함

 

@AfterAll

전체 테스트를 종료하기 전에 처음으로 한 번만 실행됨

데이터베이스를 연결을 종료할 때나 공통적으로 사용하는 자원을 해제할 때 사용

전체 테스트 시행 주기에서 한 번 만 호출되어야 하기 때문에 메서드를 static으로 선언

 

@AfterEach

각 테스트 케이스를 종료하기 전에 매번 실행

테스트 이후에 특정 데이터를 삭제해야 하는 경우 사용

각 인스턴스에 대해 메서드를 호출해야 하므로 메서드는 static이 아니어야 함


 

AssertJ로 검증문 가독성 높이기

Assertion은 기댓값과 실제 비교값을 명시하지 않으므로 비교 대상이 헷갈릴 수 있다

Assertions.assertEquals(sum, a+b);

 

이럴 때 AssertJ를 적용한 코드는 가독성을 높여준다(a와 b를 더한 값이 sum과 같아야 한다는 의미로 읽힘)

assertThat(a+b).isEqualsTo(sum);
메서드 이름 설명
isEuqalTo(A) A 값과 같은지 검증
isNotEqualTo(A) A 값과 다른지 검증
contains(A) A 값을 포함하는지 검증
doesNotContain(A) A 값을 포함하지 않는지 검증
startsWith(A) 접두사가 A인지 검증
endsWith(A) 접미사가 A인지 검증
isEmpty() 비어 있는 값인지 검증
isNotEmpty() 비어 있지 않은 값인지 검증
isPositive() 양수인지 검증
isNegative() 음수인지 검증
isGreaterThan(1) 1보다 큰 값인지 검증
isLessThan(1) 1보다 작은 값인지 검증

 

@SpringBootTest

메인 애플리케이션 클래스에 추가하는 애너테이션인 @SpringBootApplication이 있는 클래스를 찾고 그 클래스에 있는 빈을 찾은 다음 테스트용 애플리케이션 컨텍스트라는 것을 만든다

 

@AutoConfigureMockMvc

MockMvc를 생성하고 자동으로 구성하는 애너테이션

MockMvc는 애플리케이션을 서버에 배포하지 않고도 테스트용 MVC 환경을 만들어 요청 및 전송, 응답 기능을 제공하는 유틸리티 클래스

컨트롤러를 테스트할 때 사용되는 클래스