JAVA

[JAVA] API 구현 시 테스트 개발

응디 2022. 6. 2. 17:42

< 스프링 부트 슬라이스 테스트 >

 

@WebMvcTest

  • MockMvc 빈을 자동 설정 해준다. 그냥 가져와서 쓰면 됨.
  • 웹 관련 빈만 등록해준다.

@MockMvc

  • 스프링 MVC 테스트 핵심 클래스
  • 웹 서버를 띄우지 않고도 요청을 처리하는 과정을 확인가능 → 컨트롤러 테스트용으로 자주 쓰임 

 

테스트 내용 

1. 입력값들을 전달하면 JSON 응답으로 201 값이 나오는지 확인
- Location 헤더에 생성된 이벤트를 조회할 수 있는 URI 담겨있는지 확인
- id는 DB에 들어갈 때 자동 생성된 값으로 나오는지 확인

 

@RestController

  • @ResponseBody를 모든 메소드에 적용한 것과 동일

ResponseEntity를 사용하는 이유

  • 응답코드, 헤더, 본문, 모두 다루기 편한 API

Location URI 만들기

  • HATEOAS가 제공하는 linkTo(), methodOn() 사용

객체를 Json으로 변환

  • ObjectMapper 사용

@MockBean 

  • Mockito를 사용해서 mock 객체를 만들고 빈으로 등록해줌 → WebMvcTest는 웹 관련 빈만 등록 해주기 때문에 repository와 같은 것들을 테스트 할 경우 MockBean으로 등록을 안해주면 NullPointerException이 날수있다!
  • 주의! 기존 빈을 테스트용 빈이 대체 한다.

아래 예시를 살펴보자!

 

EventController.java

package me.whiteship.restapi.events;

import lombok.RequiredArgsConstructor;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.net.URI;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;


@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE)
@RequiredArgsConstructor
public class EventController {

    private final EventRepository eventRepository;

    @PostMapping
    public ResponseEntity createEvent(@RequestBody Event event) {
        Event newEvent = eventRepository.save(event);
        URI createdUri = linkTo(EventController.class).slash(newEvent.getId()).toUri();
        return ResponseEntity.created(createdUri).body(event);
    }
}

 

 

EventControllerTest.java

package me.whiteship.restapi.events;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@ExtendWith(SpringExtension.class)
@WebMvcTest // 웹과 관련된 테스트만 하는 것 -> 슬라이스 테스트
public class EventControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;

    @MockBean
    EventRepository eventRepository;

    @Test
    public void createEvent() throws Exception{
        //given
        Event event = Event.builder()
                .name("Spring")
                .description("REST API Development with Spring")
                .beginEnrollmentDateTime(LocalDateTime.of(2018, 11, 23, 14, 21))
                .closeEnrollmentDateTime(LocalDateTime.of(2018, 11, 25, 14, 21))
                .beginEventDateTime(LocalDateTime.of(2018, 11, 26, 14, 21))
                .basePrice(100)
                .maxPrice(200)
                .limitOfEnrollment(100)
                .location("강남역 D2 스타텁 팩토리")
                .build();

        event.setId(10);
        Mockito.when(eventRepository.save(event)).thenReturn(event);

        mockMvc.perform(post("/api/events/")    // post 요청을 보내고 -> perform을 하고 나면 응답이 옴
                        .contentType(MediaType.APPLICATION_JSON)    // 요청에 json을 담아서 보내고 있다고 알려줌
                        .accept(MediaTypes.HAL_JSON)   // 원하는 응답의 타입
                        .content(objectMapper.writeValueAsString(event)))   // 객체를 json으로 변환
                .andDo(print()) // 실제 응답이 어떻게 나왔는지 console에서 볼수 있음
                .andExpect(status().isCreated())
                .andExpect(jsonPath("id").exists());

        //when

        //then
    }

}

 

'JAVA' 카테고리의 다른 글

String vs StringBuffer vs StringBuilder  (0) 2022.07.05
spring boot 프로젝트 생성과 사용 이유  (0) 2022.07.04
[JAVA] 지연로딩과 조회 성능 최적화  (0) 2022.05.19
[JAVA] CRU API  (0) 2022.05.17
[JAVA] boolean @Getter  (0) 2022.03.24