❑ Hamcrest
➤ Hamcrest 란?
▶️ Hamcrest란?
🍉 Hamcrest 는 JUnit 기반의 단위 테스트에서 사용할 수 있는 Assertion Framework 이다.
🍉 JUnit에서 Assertion을 위한 다양한 메서드를 지원한다.
▶️ Hamcrest를 사용하는 이유
🍉 Assertion을 위한 매쳐(Matcher)가 자연스러운 문장으로 이어져서 가독성이 향상된다.
🍉 테스트 실패 메세지를 이해하기 쉽다.
🍉 다양한 Matcher를 제공한다.
➤ JUnit Assertion ➡️ Hamcrest Assertion 적용하기
🍇 JUnit Assertion 사용시
public class HelloJUnitTest {
@DisplayName("Hello JUnit Test")
@Test
public void assertionTest() {
String expected = "Hello, World!";
String actual = "Hello, JUnit";
assertEquals(expected, actual);
}
}
콘솔 출력 결과
expected: <Hello, World!> but was: <Hello, JUnit>
Expected :Hello, World!
Actual :Hello, JUnit
🍇 Hamcrest의 Matcher 사용시
public class HelloHamcrestTest {
@DisplayName("Hello Junit Test using hamcrest")
@Test
public void assertionTest1() {
String expected = "Hello, World!";
String actual = "Hello, Hamcrest";
assertThat(actual, is(equalTo(expected)));
}
}
콘솔 출력 결과
Expected: is "Hello, World!"
but: was "Hello, Hamcrest"
Expected :Hello, World!
Actual :Hello, Hamcrest
▶️ assertThat(actual, is(equalTo(expected)));
- JUnit의 assertEquals(expected, actual) 와 비슷하지만 더 쉽다.
▶️ JUnit의 Assertion vs Hamcrest Assertion 테스트 결과
Hamcrest의 Matcher를 사용하면 사람이 읽기 편한 자연스러운 Assertion 문장을 구성할 수 있다. ➡️ 가독성이 많이 높아진다.
테스팅 실패 메시지를 이해하기 더 쉽다.
❑ 슬라이스 테스트 (Slice Test)
➤ 슬라이스 테스트란?
각 계층에 구현한 기능들이 잘 동작하는지 특정 계층만 잘라서(Slice) 테스트하는 것
※ 스모크 테스트(Smoke Test)
소프트웨어의 본격적인 테스트에 앞서, 구축된 테스트 환경에서 테스트가 가능한지를 판단하기 위해 주요 모듈을 간단하게 테스트하는 것이다. 세세한 테스트를 하는 것이 아니라 테스팅 전에 큰 결함은 없는지 확인하는 과정이라고 볼 수 있다.
➤ API 계층 테스트
API 계층 테스트 대상은 대부분 클라이언트의 요청을 받아들이는 핸들러인 Controller 이다.
▶️ @SpringBootTest
Spring Boot 기반의 애플리케이션을 테스트하기 위한 Application Context를 생성한다.
▶️ @AutoConfigureMockMvc
Controller 테스트를 위한 애플리케이션의 자동 구성 작업을 해준다.
MocMvc 기능을 사용하기 위해서는 이 애너테이션을 추가해야 한다.
▶️ MockMvc
Controller 테스트 클래스에 DI 로 주입받은 MockMvc 는 Tomcat 같은 서버를 실행하지 않고 Spring 기반 애플리케이션의 Controller를 테스트할 수 있는 완벽한 환경을 지원해준다.
➡️ Spring MVC 테스트 프레임워크
MockMvc 객체를 통해 Controller를 호출해서 손쉽게 테스트를 진행할 수 있다.
▶️ Given
🍊 request body 에 포함시키는 요청 데이터와 동일한 역할을 하게끔 작성한다.
🍊 dto의 테스트하고자 하는 객체를 생성한다.
🍊 Gson(JSON 변환 라이브러리) 을 이용하여 dto 객체를 JSON 포맷으로 변환해준다.
▶️ When
🍊 HTTP request 에 대한 정보를 MockMvcRequestBuilders 클래스를 이용해서 빌더 패턴으로 채워준다.
🍊 MockMvc 객체의 perform() 메서드 호출
🍊 post() 메서드 : HTTP POST 메서드와 request URL을 설정한다. (다른 http 메서드도 가능)
🍊 accept() 메서드 : 클라이언트 쪽에서 리턴 받을 응답 데이터 타입으로 JSON 타입 설정
🍊 contentType() 메서드 : 서버 쪽에서 처리가능한 Content Type으로 JSON 타입 설정
🍊 content() 메서드 : request body 데이터를 설정한다. (Gson을 이용해 변환된 Json 문자열)
🍊 perform() 이 최종적으로 ResultActions 타입을 리턴한다.
⚠️ post() 메서드 사용하기 위해 import 해올 때 잘못된 경로의 post를 import하지 않도록 주의한다.
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
▶️ Then
🍊 ResultActions 객체를 이용해서 전송한 request 에 대한 검증을 수행한다.
🍊 andExpect() 메서드 : 파라미터로 입력한 매처(Matcher)로 예상되는 기대 결과를 검증한다.
🍊 status().isCreated() : response status 가 201(Created)가 맞는지 검증한다. (is뒤에 원하는 response status를 넣으면 된다.)
🍊 andReturn() : 디버깅 용도로 response로 전달되는 응답 데이터를 출력할 때 사용한다.
🍊 jsonPath() : response body의 각 property 중에서 응답으로 전달 받는 특정 값이 response body로 전송한 값과 동일한지 검증할 수 있다. jsonPath()를 사용하면 JSON 형식의 개별 property에 손쉽게 접근할 수 있다.
Member Cotroller의 getMember 테스트 예시 코드
@Test
void getMemberTest() throws Exception {
// given
long memberId = member1.getMemberId();
Member member = repository.findById(memberId).get();
String content = gson.toJson(String.valueOf(memberId));
// when
ResultActions actions =
mockMvc.perform(
get("/v11/members/" + memberId)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
// then
MvcResult result = actions
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.email").value(member.getEmail()))
.andExpect(jsonPath("$.data.name").value(member.getName()))
.andExpect(jsonPath("$.data.phone").value(member.getPhone()))
.andReturn();
}
✔️ response body 응답 데이터에 한글이 깨질 경우
resources 패키지 안에 application.yml에 들어가서 아래의 코드를 추가한다.
server:
servlet:
encoding:
force-response: true
➤ 데이터 액세스 계층 테스트
데이터 액세스 계층 테스트를 위해 테스트하려는 repository를 DI 로 주입한다.
▶️ @DataJpaTest
🥭 Repository 기능을 정상적으로 사용하기 위해 Configuration을 Spring이 자동으로 해주게 된다.
🥭 @Transactional 애너테이션을 포함하고 있기 때문에 하나의 테스트 케이스 실행이 종료되는 시점에 데이터베이스에 저장된 데이터는 rollback 된다.
🥭 여러 개의 테스트 케이스를 한꺼번에 실행시켜도 하나의 테스트 케이스가 종료될 때마다 데이터 베이스의 상태가 초기 상태를 유지한다.
▶️ Repository DI로 주입
@Autowired
private MemberRepository memberRepository;
▶️ Given
테스트 할 Entity 정보를 준비한다.
▶️ when
정보를 테스트하고자 하는 메서드를 불러서 테스트한다.
▶️ Then
정보가 잘 저장되었는지 검증(assertion) 한다.
감사합니다.
오개념에 대한 지적은 늘 환영입니다. 🤩
'TIL(Today I Learned)' 카테고리의 다른 글
7/14 (목) 테스팅(Testing) 3️⃣ - Mockito, TDD (0) | 2022.08.02 |
---|---|
7/27 (수) [Spring Security] JWT 인증(Authentication) (0) | 2022.08.02 |
8/2 (화) [Cloud] 운영 환경 구성 1️⃣ (0) | 2022.08.02 |
7/12 (화) Spring MVC 테스팅 1️⃣ (0) | 2022.08.02 |
7/21 (목) 인증 / 보안 기초 2️⃣ (0) | 2022.07.25 |