개발강의정리/Spring

[스프링 기반 REST API 개발] 2-2. Event 생성 API 구현: 201 응답 받기

nineDeveloper 2019. 12. 28.
728x90

스프링 기반 REST API 개발

2. 이벤트 생성 API 개발

포스팅 참조 정보

GitHub

공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다

해당 포스팅에 대한 내용의 GitHub 주소

실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다

https://github.com/freespringlecture/spring-rest-api-study/tree/chap02-02_201_response

해당 포스팅 참고 인프런 강의

https://www.inflearn.com/course/spring_rest-api/dashboard

실습 환경

  • Java Version: Java 11
  • SpringBoot Version: 2.1.2.RELEASE

2. Event 생성 API 구현: 201 응답 받기

@RestController

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

ResponseEntity를 사용하는 이유

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

Location URI 만들기

  • HATEOS가 제공하는 linkTo(), methodOn() 사용
  • methodOn()에서 메서드를 호출할 때 메서드에 있는 URL을 읽어와야 되는데 어떤 메서드에 있는걸 읽어와야될지 메서드를 호출해서 지정함(타입세이프)
  • 파라메터를 추가하는 바람에 nullcreateEvent()에 추가함 @RequestMapping@Controller에 있는 모든 Handler에 적용되도록 설정

객체를 JSON으로 변환

ObjectMapper 사용

테스트 할 것

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

Event 생성 API 코드 작성

1. Event 도메인 클래스에 시작일시 추가

package me.freelife.rest.events;

import lombok.*;

import java.time.LocalDateTime;

@Builder @AllArgsConstructor @NoArgsConstructor
@Getter @Setter @EqualsAndHashCode(of = "id")
public class Event {

    ...

    private LocalDateTime beginEventDateTime; //이벤트 시작일시

    ...

}

2. Event 생성 API 코드 작성

package me.freelife.rest.events;

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.mvc.ControllerLinkBuilder.linkTo;

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

    @PostMapping
    public ResponseEntity createEvent(@RequestBody Event event) {
        //EventController의 id에 해당하는 링크를 만들고 링크를 URI로 변환
        URI createdUri = linkTo(EventController.class).slash("{id}").toUri();
        event.setId(10);
        // createdUri 헤더를 가지고 201응답을 만듬
        return ResponseEntity.created(createdUri).body(event);
    }
}

3. Event 생성 API 테스트 코드 수정

package me.freelife.rest.events;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import java.time.LocalDateTime;

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;

@RunWith(SpringRunner.class)
@WebMvcTest
public class EventControllerTests {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;

    @Test
    public void createEvent() throws Exception {
        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, 24, 14, 21))
                .beginEventDateTime(LocalDateTime.of(2018, 11, 25, 14, 21))
                .endEventDateTime(LocalDateTime.of(2018, 11, 26, 14, 21))
                .basePrice(100)
                .maxPrice(200)
                .limitOfEnrollment(100)
                .location("강남역 D2 스타텁 팩토리")
                .build();

        mockMvc.perform(post("/api/events/")
                    .contentType(MediaType.APPLICATION_JSON_UTF8) //요청타입
                    .accept(MediaTypes.HAL_JSON) //받고싶은 타입
                    .content(objectMapper.writeValueAsString(event)))
                .andDo(print())
                .andExpect(status().isCreated())
                .andExpect(jsonPath("id").exists());
    }

}
728x90

댓글

💲 추천 글