반응형

 

 

 

 

 

 

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 문장을 구성할 수 있다. ➡️ 가독성이 많이 높아진다.

테스팅 실패 메시지를 이해하기 더 쉽다.

 

 

더 많은 Hamcrest Matcher

Custom Matcher

 

 

 

 

슬라이스 테스트 (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에 손쉽게 접근할 수 있다.

 

심화학습) jsonPath()

 

 

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 된다.

🥭 여러 개의 테스트 케이스를 한꺼번에 실행시켜도 하나의 테스트 케이스가 종료될 때마다 데이터 베이스의 상태가 초기 상태를 유지한다.

 

참고) @DataJpaTest 애너테이션 doc

 

 

▶️ Repository DI로 주입

 

@Autowired
private MemberRepository memberRepository;

 

 

▶️ Given

 

테스트 할 Entity 정보를 준비한다.

 

 

▶️ when

 

정보를 테스트하고자 하는 메서드를 불러서 테스트한다.

 

 

▶️ Then

 

정보가 잘 저장되었는지 검증(assertion) 한다.

 

 

 

 

테스팅 유닛 예제 코드(깃허브)

 

 

 

 

 

감사합니다.

오개념에 대한 지적은 늘 환영입니다. 🤩

 

 

반응형