작성한 코드가 의도대로 잘 동작하고 예상치 못한 문제가 없는지 확인할 목적으로 작성하는 코드
- 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 saveId = menuService.save(americano);
//then : 메뉴가 잘 추가되었는지 검증
final Menu saveMenu = menuService.findById(saveId).get();
assertThat(saveMenu.getName()).isEqualTo(name);
assertThat(saveMenu.getPrice()).isEqualTo(price);
spring-boot-starter-test 스타터에 테스트를 위한 도구가 모여있음.
- JUnit : 자바 플그래밍 언어용 단위 테스트 프레임워크
- Spring Test & Spring Boot Test : 스프링 부트 애플리케이션을 위한 통합 테스트 지원
- AssertJ : 검증문인 어설션을 작성하는 데 사용되는 라이브러리
- Hamcrest : 표현식을 이해하기 쉽게 만드는 데 사용되는 Matcher 라이브러리
- Mockito : 테스트에 사용할 가짜 객체인 목 객체를 쉽게 만들고, 관리하고, 검증할 수 있게 지원하는 테스트 프레임워크
- JSONassert : JSON용 어설션 라이브러리
- JsonPath : JSON 데이터에서 특정 데이터를 선택하고 검색하기 위한 라이브러리
자바 언어를 위한 단위 테스트 프레임워크
※ 단위 테스트 : 작성한 코드가 의도대로 작동하는지 작은 단위로 검증하는 것
- 테스트 방식을 구분할 수 있는 애너테이션을 제공
@Test애너테이션으로 메서드를 호출할 때마다 새 인스턴스를 생성, 독립 테스트 가능- 예상 결과를 검증하는 어설션 메서드 제공
- 사용 방법이 단순, 테스트 코드 작성 시간이 적음
- 자동 실행, 자체 결과를 확인하고 즉각적인 피드백을 제공
@DisplayName("1 + 2는 3이다")
@Test
public void junitTest() {
int a = 1;
int b = 2;
int sum = 3;
Assertions.assertEquals(a + b, sum);
}

@DisplayName("1 + 3는 4이다")
@Test
public void junitFailedTest() {
int a = 1;
int b = 3;
int sum = 3; // 원래 정답은 4이어야 함
Assertions.assertEquals(a + b, sum);
}

@BeforeAll: ( static ) 전체 테스트를 시작하기 전에 처음으로 한 번만 실행
데이터베이스를 연결하거나 테스트 환경을 초기화 할 때 사용BeforeEach: 테스트 케이스를 시작하기 전에 매번 실행
테스트 메서드에서 사용하는 객체를 초기화하거나 테스트에 필요한 값을 미리 넣을 때 사용AfterAll: ( static ) 전체 테스트를 마치고 종료하기 전에 한 번 실행
데이터베이스 연결을 종료하거나 공통적으로 사용되는 자원을 해제할 때 사용AfterEach: 각 테스트 케이스를 종료하기 전 매번 실행
테스트 이후에 특정 데이터를 삭제해야하는 경우 사용
@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("test1");
}
@Test
public void test3(){
System.out.println("test1");
}
@AfterAll // 전체 테스트를 마치고 종료하기 전에 1회 실행하므로 메서드는 static으로 선언
static void afterAll(){
System.out.println("@AfterAll");
}
@AfterEach // 테스트 케이스를 종료하기 전마다 실행
public void afterEach(){
System.out.println("@AfterEach");
}

JUnit과 함께 사용해 검증문의 가독성을 높여주는 라이브러리
Assertions.assertEquals(sum, a + b);
assertThat(a + b).isEqualTo(sum);
| 메서드 이름 | 설명 |
|---|---|
isEqualTo(A) | A 값과 같은지 검증 |
isNotEqualTo(A) | A 값과 다른지 검증 |
contains(A) | A 값을 포함하는지 검증 |
doesNotContain(A) | A 값을 포함하지 않는지 검증 |
startsWith(A) | 접두사가 A인지 검증 |
endsWith(A) | 접미사가 A인지 검증 |
isEmpty() | 비어 있는 값인지 검증 |
isNotEmpty(A) | 비어 있지 않는 값인지 검증 |
isPositive() | 양수인지 검증 |
isNegative(A) | 음수인지 검증 |
isGreaterThan(A) | 1보다 큰 값인지 검증 |
isLessThan(A) | 1보자 작은 값인지 검증 |
@SpringBootTest:@SpringBootApplication이 있는 클래스를 찾고 그 클래스에 포함되어 있는 빈을 찾은 다음에 테스트용 애플리케이션 컨텍스트 생성AutoConfigureMockMvc: MockMvc를 자동 생성하고 자동으로 구성하는 애너테이션
※ MockMvc는 애플리케이션을 서버에 배포하지 않고도 테스트용 MVC 환경을 만들어 요청 및 전송, 응답 기능을 제공하는 유틸리티 클래스 - 컨트롤러 테스트 시 사용BeforeEach:MockMvcSetUp()메서드를 실행해 MockMvc를 설정AfterEach:cleanUp()메서드를 실행해 member 테이블에 있는 데이터들을 모두 삭제
@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();
}
}
perform(): 요청 전송 -ResultActions객체는 반환값을 검증하고 확인하는andExcept()메서드를 제공accpet(): 요청을 보낼 때 무슨 타입으로 응답을 받을지 결정하는 메서드andExcept(): 응답 검증 - 응답 코드가 200인지 확인- `jsonPath("{필드명}" : JSON의 응답값을 가져요는 역할 - 0번째 배열에 들어있는 객체의 id, name 값을 가져오고, 저장된 값과 같은지 확인
@DisplayName("getAllMembers: 아티클 조회에 성공한다.")
@Test
public void getAllMembers() throws Exception {
// given
final String url = "/test";
Member savedMember = memberRepository.save(new Member(1L, "홍길동"));
// when
final ResultActions result = mockMvc.perform(get(url) // 1
.accept(MediaType.APPLICATION_JSON)); // 2
// then
result
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").value(savedMember.getId())) // 3
//4 응답의 0번째 값이 DB에 저장한 값과 같은지 확인
.andExpect(jsonPath("$[0].name").value(savedMember.getName()));
}
}