Java_테스트

Minki CHO·2023년 2월 4일
0

CodeStates

목록 보기
42/43

슬라이스 테스트

단위 테스트의 경우
:일반적으로 특정 모듈이나 계층, 기술에 의존적이지 않도록 작성하는 것이 좋음

하나의 애플리케이션은 계층별로 역할이 있고, 계층별로 서로 연동되기 때문에
각각의 계층별로 잘 활동하는지 테스트를 진행해야 함
마지막에는 통합 테스트를 통해 계층 간의 연동에 문제가 없는지 확인해야 테스트 작업이 마무리 됨

슬라이스 테스트Slice Test
:각 계층에 구현해 놓은 기능들이 잘 작동하는지 특정 계층만 잘라서Slice 테스트 하는 것

API 계층 테스트

API 계층 테스트 대상
:대부분 클라이언트의 요청을 받아들이는 핸들러인 Controller임

controller 테스트를 위한 테스트 클래스 구조
postMember() 핸들러 메서드 테스트

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.test.web.servlet.MockMvc;

@SpringBootTest       // 1)
@AutoConfigureMockMvc  // 2)
public class ControllerTestDefaultStructure {
		// 3)
    @Autowired
    private MockMvc mockMvc;
    
		// 4) 
    @Test
    public void postMemberTest() {
        // given 5) 테스트용 request body 생성
        
        // when 6) MockMvc 객체로 테스트 대상 Controller 호출
        
        // then 7) Controller 핸들러 메서드에서 응답으로 수신한 HTTP Status 및 response body 검증 
    }
}

1) @SpringBootTest
:Spring Boot 기반의 애플리케이션을 테스트하기 위한 Application Context를 생성
(Application Context에는 애플리케이션에 필요한 Bean 객체들이 등록되어 있음)

2) @AutoConfigureMockMvc
:Controller 테스트를 위한 애플리케이션의 자동 구성 작업을 함
:3) MockMvc 기능 사용하려면 @AutoConfigureMockMvc 애너테이션 추가해야 함

3) private MockMvc mockMvc
:DI로 주입받은 MockMvc는 Tomcat 같은 서버를 실행하지 않고
Spring 기반 애플리케이션의 Controller를 테스트 할 수 있는 완벽한 환경을 지원해주는 Spring MVC 테스트 프레임워크임

import com.codestates.member.dto.MemberDto;
import com.google.gson.Gson;
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.transaction.annotation.Transactional;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private Gson gson;

    @Test
    void postMemberTest() throws Exception {
        // given  1)
        MemberDto.Post post = new MemberDto.Post("hgd@gmail.com",
                                                        "홍길동",
                                                    "010-1234-5678");
        String content = gson.toJson(post); // 2)

        // when
        ResultActions actions =
                mockMvc.perform(                        // 3)
	                                post("/v11/members")  // 4)
                                        .accept(MediaType.APPLICATION_JSON) // 5)
                                        .contentType(MediaType.APPLICATION_JSON) // 6)
                                        .content(content)   // 7)
                                );

        // then
        actions
                .andExpect(status().isCreated()) // 8)
                .andExpect(header().string("Location", is(startsWith("/v11/members/"))));  // 9)
    }
}

1) 2)

//given
MemberDto.Post post = new MemberDteo.post("hgd@gmail.com","홍길동","010-1234-5678")
String content = gson.toJson(post);

:Postman 사용할 때 request body에 포함시키는 요청 데이터와 동일한 역할을 함
:Gson이라는 JSON 변환 라이브러리를 이용해 1)에서 생성한 MemberDto.Post post 객체를 JSON 포맷으로 변환

(Gson 라이브러리를 사용하기 위해서는
build.gradle에 아래 내용을 추가해야 함

dependencies{
implementation 'com.google.code.gson:gson'
}

)

3) 4) 5) 6) 7)

//when
ResultActions actions =
                mockMvc.perform( 
	                            post("/v11/members")
                                   .accept(MediaType.APPLICATION_JSON)
                                  .contentType(MediaType.APPLICATION_JSON)                                   .content(content)  
                                );

:MockMvc로 테스트 대상 Controller의 핸들러 메서드에 요청을 전송하기 위해서는
기본적으로 perform() 메서드를 호출해야하고
perform() 메서드 내부에 Controller 호출을 위한 세부적인 정보들이 포함됨
:4)post() :HTTP POST METHOD와 request URL을 설정
:5)accept() :클라이언트 쪽에서 리턴받을 응답 데이터 타입으로 JSON 타입을 설정<노이해중>
:6)contentType() :서버쪽에서 처리 가능한 Content Type으로 JSON 타입을 설정<노이해중>
:7)content() : request body 데이터를 설정
:request body에 전달하는 데이터는 2)에서 Gson 라이브러리를 이용해 변환된 JSON 문자열임

8) 9)

//then
actions
    .andExpect(status().isCreated())
    .andExpect(header().string("Location", is(startsWith("/v11/members/")))); 

:MockMvc의 perform() 메서드는 ResultActions 타입의 객체를 리턴함
:이 ResultAtions 객체를 이용해 전송한 request에 대한 검증을 수행할 수 있음<노이해중>
:8)andExpect() :파라미터로 입력한 매쳐Matcher로 예상되는 기대 결과를 검증할 수 있음, status().isCreated()를 통해 response status가 201Created인지 매치시킴
:9)header().string("Location",isstartsWith("/v11/members/")) :HTTP 헤더에 추가된 Location의 문자열 값이 "/v11/members/"로 시작하는지 검증

getMember() 핸들러 메서드 테스트

import com.codestates.member.dto.MemberDto;
import com.google.gson.Gson;
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.transaction.annotation.Transactional;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@Transactional
@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private Gson gson;

    ...
    ...

    @Test
    void getMemberTest() throws Exception {
        // ===== 1) postMember()를 이용한 테스트 데이터 생성 시작
        // given
        MemberDto.Post post = new MemberDto.Post("hgd@gmail.com","홍길동","010-1111-1111");
        String postContent = gson.toJson(post);

        ResultActions postActions =
                mockMvc.perform(
                        post("/v11/members")
                                .accept(MediaType.APPLICATION_JSON)
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(postContent)
                );
        // ===== 1) postMember()를 이용한 테스트 데이터 생성 끝

        // 2)
        String location = postActions.andReturn().getResponse().getHeader("Location"); // "/v11/members/1"

        // when / then
    mockMvc.perform(
                    get(location)      // 3)
                         .accept(MediaType.APPLICATION_JSON)
                		 )
           .andExpect(status().isOk())    // 4)
           .andExpect(jsonPath("$.data.email").value(post.getEmail())) // 5)
           .andExpect(jsonPath("$.data.name").value(post.getName())) // 6)
           .andExpect(jsonPath("$.data.phone").value(post.getPhone()));  // (7)
    }
}

:1) 2)

//1
// given
        MemberDto.Post post = new MemberDto.Post("hgd@gmail.com","홍길동","010-1111-1111");
        String postContent = gson.toJson(post);

        ResultActions postActions =
                mockMvc.perform(
                        post("/v11/members")
                                .accept(MediaType.APPLICATION_JSON)
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(postContent)
                );
//2)
        String location = postActions.andReturn().getResponse().getHeader("Location");

:1) postMember() 핸들러 메서드 테스트할 때와 동일
:2) postMember()의 response에 전달되는 Location header 값을 가져오는 로직
:postActions.andReturn().getResponse().getHeader("Location")으로 접근해서 Location header 값을 얻을 수 있음

profile
Developer

0개의 댓글