반응형
11-08 23:08
Today
Total
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
관리 메뉴

개발하는 고라니

[Spring Boot] Controller Test 본문

Framework/Spring Boot

[Spring Boot] Controller Test

조용한고라니 2021. 12. 4. 17:41
반응형

Servicee 나 Repository에 대해 테스트 코드를 짜는 것은 조금은 익숙하나, Controller 레이어를 구성하고 테스트 하기 위해서는 Postman이나 Web UI 테스트를 진행해왔다. 이번에는 어플리케이션 수준에서 Controller 테스트를 하는 방법을 간단하게 알아보고자 한다.

 

Environment

- Junit 5

- Spring Boot 2.1.7

- JPA (Hibernate)

Controller Test

* Service, Repository, DTO 및 Entity에 대한 코드는 따로 명시하진 않는다.

 

Controller에 대해 테스트를 하려면 Mock이라는 개념이 필요한데, 이에 대해서는 다음에 자세히 알아보도록 하고, 이번에는 어떻게 사용하는지만 알아보자.

package org.gorany.bootbook.api.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

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.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

/**
 * @WebMvcTest
 * - JPA 기능은 동작하지 않는다.
 * - 여러 스프링 테스트 어노테이션 중, Web(Spring MVC)에만 집중할 수 있는 어노테이션
 * - @Controller, @ControllerAdvice 사용 가능
 * - 단, @Service, @Repository등은 사용할 수 없다.
 * */
@WebMvcTest(HelloController.class)
class HelloControllerTest {

    @Autowired
    /**
     * 웹 API 테스트할 때 사용
     * 스프링 MVC 테스트의 시작점
     * HTTP GET,POST 등에 대해 API 테스트 가능
     * */
    MockMvc mvc;

    @Test
    @DisplayName("Hello Test")
    void Hello_Test() throws Exception {
        //given
        String hello = "hello";
        //when

        //then
        mvc.perform(get("/hello")) //MockMvc를 통해 /hello 주소로 GET 요청
             //mvc.perform()의 결과를 검증
            .andExpect(status().isOk()) //200 상태
            .andExpect(content().string(hello)); //응답 본문의 내용을 검증
    }

    @Test
    @DisplayName("헬로 디티오 컨트롤러 테스트")
    void HelloControllerDtoTest() throws Exception {
        //given
        String name = "Test";
        int amount = 10000;
        //when
        //then
        mvc.perform(get("/hello/dto")
                .param("name", name)
                .param("amount", Integer.toString(amount))
            )
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value(name))
            .andExpect(jsonPath("$.amount").value(amount));
    }
}

위와 같이 오직 Controller에 대해서만 테스트 검증을 할 때는 @WebMvcTest 를 사용하면 된다. 하지만 @Service, @Repository 등도 같이 사용해야하는 로직이라면 어떻게 해야할까? 그리고 JPA도 사용해야한다면?

@SpringBootTest 어노테이션을 사용해야 한다. 하지만 이 어노테이션만 가지고는 MockMvc를 사용할 수 없다. 따라서 어노테이션이 하나 더 필요하다. -> @AutoConfigureMockMvc

 

 

package org.gorany.bootbook.api.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.gorany.bootbook.api.dto.PostsSaveRequestDto;
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;

@SpringBootTest
@AutoConfigureMockMvc
class PostsControllerTest {

    @Autowired
    ObjectMapper mapper;

    @Autowired
    MockMvc mvc;

    private static final String BASE_URL = "/api/v1";

    @Test
    @DisplayName("저장 테스트")
    void save_test() throws Exception {
        //given
        String title = "Test title";
        String content = "Test content";
        String author = "gorany";
        //when
        /**
         * Object를 JSON으로 변환
         * */
        String body = mapper.writeValueAsString(
            PostsSaveRequestDto.builder().author(author).content(content).title(title).build()
        );
        //then
        mvc.perform(post(BASE_URL + "/posts")
                .content(body) //HTTP Body에 데이터를 담는다
                .contentType(MediaType.APPLICATION_JSON) //보내는 데이터의 타입을 명시
            )
            .andExpect(status().isOk())
            .andExpect(content().string("1"));
    }
}

 

#References

스프링 부트와 AWS로 혼자 구현하는 웹 서비스, 이동욱, 프리렉

반응형
Comments