ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] REST API 만들기(7) - Controller 구현 및 단위 테스트(Junit5)
    Spring Boot/2.7.x - REST API 만들기 2022. 10. 5. 23:22
    반응형

    REST API 만들기(7) - Controller 구현 및 단위 테스트

    TodoController.java를 구현한 후 JUnit5을 사용하여 단위 테스트를 작성하세요.

    1. TodoController.java

    package com.example.springbootrestapi.web.controller;
    
    import com.example.springbootrestapi.domain.Todo;
    import com.example.springbootrestapi.service.TodoService;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    
    @Slf4j
    @RequiredArgsConstructor
    @RestController
    public class TodoController {
    
      private final TodoService todoService;
    
      /**
       * To-Do 조회
       */
      @PostMapping(
          value = "/api/todos",
          consumes = MediaType.APPLICATION_JSON_VALUE,
          produces = MediaType.APPLICATION_JSON_VALUE)
      public List<Todo.Response> getTodos(
          HttpServletRequest request,
          HttpServletResponse response,
          @RequestBody Todo.Request todoRequest) {
        log.info("todoRequest:[{}]", todoRequest.toString());
        return todoService.getTodos(todoRequest);
      }
    
      /**
       * To-Do 조회
       */
      @GetMapping(
          value = "/api/todo/{id}",
          consumes = MediaType.APPLICATION_JSON_VALUE,
          produces = MediaType.APPLICATION_JSON_VALUE)
      public Todo.Response getTodoById(
          HttpServletRequest request,
          HttpServletResponse response,
          @PathVariable int id) {
        log.info("id:[{}]", id);
        return todoService.getTodoById(id);
      }
    
      /**
       * To-Do 저장
       */
      @PostMapping(
          value = "/api/todo",
          consumes = MediaType.APPLICATION_JSON_VALUE,
          produces = MediaType.APPLICATION_JSON_VALUE)
      public Todo.Response insertTodo(
          HttpServletRequest request,
          HttpServletResponse response,
          @RequestBody Todo.Request todoRequest) {
        log.info("todoRequest:[{}]", todoRequest.toString());
        return todoService.insertTodo(todoRequest);
      }
    
      /**
       * To-Do 수정
       */
      @PutMapping(
          value = "/api/todo",
          consumes = MediaType.APPLICATION_JSON_VALUE,
          produces = MediaType.APPLICATION_JSON_VALUE)
      public Todo.Response updateTodo(
          HttpServletRequest request,
          HttpServletResponse response,
          @RequestBody Todo.Request todoRequest) {
        log.info("todoRequest:[{}]", todoRequest.toString());
        return todoService.updateTodo(todoRequest);
      }
    
      /**
       * To-Do 삭제
       */
      @DeleteMapping(
          value = "/api/todo/{id}",
          consumes = MediaType.APPLICATION_JSON_VALUE,
          produces = MediaType.APPLICATION_JSON_VALUE)
      public Todo.Response deleteTodo(
          HttpServletRequest request,
          HttpServletResponse response,
          @PathVariable int id) {
        log.info("id:[{}]", id);
        return todoService.deleteTodoById(id);
      }
    }


    2. TestTodoController.java

    package com.example.springbootrestapi.web.controller;
    
    import static org.hamcrest.Matchers.equalTo;
    import static org.hamcrest.Matchers.is;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
    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.request.MockMvcRequestBuilders.put;
    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
    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 com.example.springbootrestapi.domain.Todo;
    import com.example.springbootrestapi.mapper.TodoMapper;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import javax.annotation.Resource;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    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.context.ActiveProfiles;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.ResultActions;
    import org.springframework.transaction.annotation.Transactional;
    
    @AutoConfigureMockMvc
    @SpringBootTest
    @ActiveProfiles("local")
    class TodoControllerTest {
    
      @Resource
      TodoMapper todoMapper;
    
      @Resource
      MockMvc mockMvc;
    
      @Resource
      ObjectMapper objectMapper;
    
      @Transactional
      @DisplayName("getTodos_To-Do 목록 조회")
      @Test
      void testGetTodos() throws Exception {
    
        // Given
        insertTodo("Title Junit Test Insert 01", "Description Junit Test Insert 01", false);
        insertTodo("Title Junit Test Insert 02", "Description Junit Test Insert 02", true);
        insertTodo("Title Junit Test Insert 03", "Description Junit Test Insert 03", false);
        insertTodo("Title Junit Test Insert 04", "Description Junit Test Insert 04", true);
        insertTodo("Title Junit Test Insert 05", "Description Junit Test Insert 05", false);
    
        String url = "/api/todos";
        Todo.Request todoRequest = Todo.Request.builder()
            .title("Title Junit Test Insert")
            .description("Description Junit Test Insert")
            .completed(true)
            .build();
    
        // When
        ResultActions resultActions = mockMvc.perform(
            post(url)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(todoRequest))
        );
    
        // Then
        resultActions
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.length()", is(2)))
            .andDo(print());
      }
    
      @Transactional
      @DisplayName("getTodoById_To-Do 상세 조회")
      @Test
      void testGetTodoById() throws Exception {
    
        // Given
        String title = "Title Junit Test Insert";
        String description = "Description Junit Test Insert";
        Boolean completed = false;
        int insertId = insertTodo(title, description, completed);
    
        String url = "/api/todo/" + insertId;
    
        // When
        ResultActions resultActions = mockMvc.perform(
            get(url)
                .contentType(MediaType.APPLICATION_JSON)
        );
    
        // Then
        resultActions
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.title", equalTo(title)))
            .andExpect(jsonPath("$.description", equalTo(description)))
            .andExpect(jsonPath("$.completed", equalTo(completed)))
            .andDo(print());
      }
    
      @Transactional
      @DisplayName("insertTodo_To-Do 저장")
      @Test
      void testInsertTodo() throws Exception {
    
        // Given
        String url = "/api/todo";
        Todo.Request todoRequest = Todo.Request.builder()
            .title("Title Junit Test Insert")
            .description("Description Junit Test Insert")
            .completed(true)
            .build();
    
        // When
        ResultActions resultActions = mockMvc.perform(
            post(url)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(todoRequest))
        );
    
        // Then
        resultActions
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.title", equalTo(todoRequest.getTitle())))
            .andExpect(jsonPath("$.description", equalTo(todoRequest.getDescription())))
            .andExpect(jsonPath("$.completed", equalTo(todoRequest.getCompleted())))
            .andDo(print());
      }
    
      @Transactional
      @DisplayName("updateTodo_To-Do 수정")
      @Test
      void testUpdateTodo() throws Exception {
    
        // Given
        String title = "Title Junit Test Insert";
        String description = "Description Junit Test Insert";
        boolean completed = false;
        int insertId = insertTodo(title, description, completed);
    
        String url = "/api/todo";
        Todo.Request todoRequest = Todo.Request.builder()
            .id(insertId)
            .title("Title Junit Test Update")
            .description("Description Junit Test Update")
            .completed(true)
            .build();
    
        // When
        ResultActions resultActions = mockMvc.perform(
            put(url)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(todoRequest))
        );
    
        // Then
        resultActions
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.title", equalTo(todoRequest.getTitle())))
            .andExpect(jsonPath("$.description", equalTo(todoRequest.getDescription())))
            .andExpect(jsonPath("$.completed", equalTo(todoRequest.getCompleted())))
            .andDo(print());
      }
    
      @Transactional
      @DisplayName("deleteTodo_To-Do 삭제")
      @Test
      void testDeleteTodo() throws Exception {
    
        // Given
        String title = "Title Junit Test Insert";
        String description = "Description Junit Test Insert";
        Boolean completed = false;
        int insertId = insertTodo(title, description, completed);
    
        String url = "/api/todo/" + insertId;
    
        // When
        ResultActions resultActions = mockMvc.perform(
            delete(url)
                .contentType(MediaType.APPLICATION_JSON)
        );
    
        // Then
        resultActions
            .andExpect(status().isOk())
            .andDo(print());
      }
    
      /**
       * To-Do 저장
       */
      int insertTodo(
          String title,
          String description,
          Boolean completed) {
    
        Todo.Request todoRequest = Todo.Request.builder()
            .title(title)
            .description(description)
            .completed(completed)
            .build();
    
        todoMapper.insertTodo(todoRequest);
    
        return todoRequest.getId();
      }
    }


    3. 단위 테스트 확인
    좌측에 초록색 버튼(Run Test) 클릭 및 클래스 또는 메소드 내에서 우클릭하여 Run 클릭하여 단위 테스트가 정상적으로 동작하는지 확인하세요. (단축키 : Ctrl + Shift + F10)


    소스 코드는 Github Repository - https://github.com/tychejin1218/springboot-rest-api (branch : section07) 를 참조하세요.

    GitHub에서 프로젝트 복사하기(Get from Version Control) - https://tychejin.tistory.com/325

    반응형

    댓글

Designed by Tistory.