테스트 코드란?
테스트 코드는 test 디렉터리에서 작업한다.
테스트 코드에도 다양한 패턴이 있다. 그중 given-when-then 패턴인데. given-when-then 패턴은 테스트 코드를 세 단계로 구분해 작성하는 방식을 말합니다.given은 테스트 실행을 준비하는 단계, when 은 테스트를 진행하는 단계, then은 테스트 결과를 검증하는 단계 이다.
Junit이란?
Junit은 자바 언어를 위한 단위 테스트 프레임워크이다. 단위 테스트라는 말은 작성한 코드가 의도대로 작동하는지 작은 단위로 검증하는 것을 의미한다. 단위는 보통 메서드가 된다.Junit을 사용한다면 단위 테스트를 작성하고 테스트 하는 데 도움을 준다.사용법도 간단하여 쉽고 테스트 결과가 직관적이라 좋다.
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 애너테이션
전체 테스트를 시작하기 전에 처음으로 한 번만 실행합니다. 예를 들어 데이터베이스를 연결해야 하거나 테스트 환경을 초기화할 때 사용됩니다. 이 애너테이션은 전체 테스트 실행 주기에서 한 번 만 호출되어야 하기 때문에 메서드를 static으로 선언해야 합니다.
@BeforeEach 애너테이션
테스트 케이스를 시작하기 전에 매번 실행합니다. 예를 들어 테스트 메서드에서 사용하는 객체를 초기화하거나 테스트에 필요한 값을 미리 넣을 때 사용할 수 있습니다. 각 인스턴스에 대해 메서드 를 호출해야 하므로 메서드는 static이 아니어야 합니다.
@AfterAll 애너테이션
전체 테스트를 마치고 종료하기 전에 한 번만 실행합니다. 예를 들어 데이터베이스 연결을 종료할 때나 공통적으로 사용하는 자원을 해제할 때 사용할 수 있습니다. 전체 테스트 실행 주기에서 한 번만 호출되어야 하므로 메서드를 static으로 선언해야 합니다.
@AfterEach 애너테이션
각 테스트 케이스를 종료하기 전 매번 실행합니다. 예를 들어 테스트 이후에 특정 데이터를 삭제해 야 하는 경우 사용합니다. @BeforeEach 애너테이션과 마찬가지로 메서드는 static이 아니어야 합니다.
AssertJ로 검증문 가독성 높이기
메서드 이름 | 설명 |
isEqualTo(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 //테스트용 애플리케이션 컨텍스트 생성
@AutoConfigureMockMvc //MockMvc 생성 및 자동 구성
class TestControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@Autowired
private MemberRepository memberRepository;
@BeforeEach //테스트 실행 전 실행하는 메서드
public void mockMvcSetUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@AfterEach //테스트 실행 후 실행하는 메서드
public void cleanUp(){
memberRepository.deleteAll();
}
}
@SpringBootTest
@SpringBootTest 애너테이션은 메인 애플리케이션 클래스에 추가하는 애너테이션인 @SpringBootApplication이 있는 클래스를 찾고 그 클래스에 포함되어 있는 빈을 찾은 다음 테스트용 애플리케이션 컨텍스트라는 것을 만듭니다.
@AutoConfigureMockMvc
@AutoConfigureMockMvc는 MockMvc를 생성하고 자동으로 구성하는 애너테이션입니다.
MockMvc는 애플리케이션을 서버에 배포하지 않고도 테스트용 MVC 환경을 만들어 요청 및 전송, 응답 기능을 제공하는 유틸리티 클래스입니다. 즉, 컨트롤러를 테스트할 때 사용되는 클래스입 니다.
@BeforeEach
테스트를 실행하기 전에 실행하는 메서드에 적용하는 애너테이션입니다. 여기서는 MockMvcSetUp() 메서드를 실행해 MockMvc를 설정해줍니다.
@AfterEach
테스트를 실행한 이후에 실행하는 메서드에 적용하는 애너테이션입니다. 여기서는 cleanUp() 메서드를 실행해 member 테이블에 있는 데이터들을 모두 삭제해줍니다.
package me.kimgunwoo.springbootstudy.chaptor03;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest //테스트용 애플리케이션 컨텍스트 생성
@AutoConfigureMockMvc //MockMvc 생성 및 자동 구성
class TestControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@Autowired
private MemberRepository memberRepository;
@BeforeEach //테스트 실행 전 실행하는 메서드
public void mockMvcSetUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@AfterEach //테스트 실행 후 실행하는 메서드
public void cleanUp(){
memberRepository.deleteAll();
}
@DisplayName("getAllMember: 아티클 조회에 성공한다.")
@Test
public void getAllMembers()throws Exception{
//given
final String url ="/test";
Member saveMember = memberRepository.save(new Member(1L,"홍길동"));
//when
final ResultActions result = mockMvc.perform(get(url).accept(MediaType.APPLICATION_JSON));
//then
result.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").value(saveMember.getId()))
.andExpect(jsonPath("$[0].name").value(saveMember.getName()));
}
}
Given | 멤버를 저장합니다. |
When | 멤버가 리스트를 조회하는 API를 호출합니다. |
Then | 응답 코드가 200 OK이고, 반환받은 값 중에 0번째 요소의 id와 name이 저장된 값과 같은지 확인합니다. |
- perform() 메서드: 요청을 전송하는 역할을 합니다. 이 메서드는 ResultActions 객체를 반환하며, 이 객체는 반환값을 검증하고 확인하는 andExpect() 메서드를 제공합니다.
- andExpect() 메서드: 응답을 검증합니다. TestController에서 생성된 API는 응답으로 OK(200)을 반환하므로, 이를 확인하기 위해 isOk 메서드를 사용합니다.
- accept() 메서드: 요청을 보낼 때 받을 응답의 타입을 결정합니다. 다양한 타입 중에서 JSON을 받기로 명시할 수 있습니다.
- jsonPath("$[0].${필드명"}: JSON 응답값에서 특정 필드의 값을 가져오는 역할을 합니다. 이를 통해 0번째 배열에 들어있는 객체의 id와 name 값을 가져와 저장된 값과 비교할 수 있습니다.
코드 | 매핑 메서드 | 설명 |
200 OK | isOk() | HTTP 응답 코드가 200 OK인지 검증 |
201 Created | isCreated() | HTTP 응답 코드가 201 Created인지 검증 |
400 Bad Request | isBadRequest() | HTTP 응답 코드가 400 Bad Request인지 검증 |
403 Forbidden | isForbidden() | HTTP 응답 코드가 403 Forbidden 인지 검증 |
404 Not Found | isNotFound() | HTTP 응답 코드가 404 Not Found인지 검증 |
400번대 응답 코드 | is4xxClientError() | HTTP 응답 코드가 400번대 응답 코드인지 검증 |
500 Internal Server Error | isinternalServerError() | HTTP 응답 코드가 500 Internal Server Error인지 검증 |
500번대 응답 코드 | is5xxServerError() | HTTP 응답 코드가 500번대 응답 코드인지 검증 |
'Spring공부' 카테고리의 다른 글
스프링 부트3로 블로그 만들기 (0) | 2024.05.20 |
---|---|
데이터베이스 (0) | 2024.05.17 |
스프링 부트 구조 살펴보기 (0) | 2024.05.14 |
스프링 부트 (0) | 2024.05.14 |
자바 백엔드 개발자가 알아주면 좋은 지식. (0) | 2024.05.14 |