[Spring REST API #2] Spring REST API 클래스 생성 및 201 테스트
- 📚 Spring/Spring REST
- 2020. 7. 19. 00:51
Spring REST API 테스트 클래스 생성 및 201 응답
의존성
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
소스 코드
package org.kyhslam.rest;
import lombok.*;
import javax.persistence.*;
import java.time.LocalDateTime;
@Builder @AllArgsConstructor @NoArgsConstructor
@Setter @Getter @EqualsAndHashCode(of = "id")
@Entity
public class Event {
@Id @GeneratedValue
private Integer id;
private String name;
private String description;
private LocalDateTime beginEnrollmentDateTime;
private LocalDateTime closeEnrollmentDateTime;
private LocalDateTime beginEventDateTime;
private LocalDateTime endEventDateTime;
private String location; // (optional)
private int basePrice; // (optional)
private int maxPrice; // (optional)
private int limitOfEnrollment;
private boolean offline;
private boolean free;
@Enumerated(EnumType.STRING)
private EventStatus eventStatus;
}
-
이벤트 엔티티의 소스코드
-
@Enumerated(EnumType.STRING) 을 통해 현재 Enum값이 문자열로 나타나도록 한다.
-
Default 값인 ORDINAL로 할 경우 EnumType의 순서가 바뀔 시 에러가 날 수 있으므로 문자열로 나타내게 하는것이 바람직하다
package org.kyhslam.rest;
public enum EventStatus {
DRAFT, PUBLISHED, BEGAN_ENROLLMENT;
}
package org.kyhslam.rest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
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;
@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_UTF8_VALUE)
public class EventController {
@Autowired
EventRepository eventRepository;
@PostMapping
public ResponseEntity createEvent(@RequestBody Event event){
Event newEvent = eventRepository.save(event);
URI createdUri = ControllerLinkBuilder.linkTo(EventController.class).slash(newEvent.getId()).toUri();
return ResponseEntity.created(createdUri).body(event);
}
}
-
HTTP요청을 처리하는 컨트롤러 이다.
-
@RequestMapping 어노테이션을 통해 이 컨트롤러가 /api/events/ URL과 매핑된 요청을 처리한다. 또한 HAL_JSON_UTF8_VALUE 형태로서 값을 반환한다.
-
@RequestBody를 통해 Body에 있는 정보가 자동적으로 Event 객체로 역질렬화되어 매핑된다.
-
HATEOS가 제공하는 linkTo 메서드를 통해 현 EventController의 URL에 대한 링크 정보를 쉽게 추가할 수 있다. 여기서는 save된 객체에서 자동적으로 할당된 ID가 포함된 URL을 Header에 넣어서 반환한다.
-
ResponseEntity는 HTTP 응답에 대한 정보를 가지고 있는 객체이다.
테스트 코드
package org.kyhslam.rest;
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 org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.time.LocalDateTime;
@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")
.beginEnrollmentDateTime(LocalDateTime.of(2018,11,23,14,21))
.closeEnrollmentDateTime(LocalDateTime.of(2018,11,23,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(MockMvcRequestBuilders.post("/api/events/")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaTypes.HAL_JSON)
.content(objectMapper.writeValueAsString(event)))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isCreated());
}
}
-
빌더를 써서 이벤트 객체를 생성하여 테스트하는 코드.
-
생성한 이벤트 객체를 /api/events/ 경로로 POST 메서드를 통해 이벤트 데이터를 생성하는 로직을 검사하는 테스트
-
실제 웹 컨테이너를 구동하지 않고 MockMvc 를 써서 테스트를 진행할 수 있다. 웹 컨테이너가 구동되지 않는 만큼 테스트를 더 빨리 돌릴 수 있다.
-
ObjectMapper는 객체를 JSON으로 변환해 준다.
-
andDo(print()) 를 사용하면 테스트 콘솔창에 해당 Request 및 Response를 볼 수 있어 디버깅하기 편하다.
-
andExpect 메서드를 통해서 어떤 응답이 올지 체크할 수 있다.
-
HttpHeaders에 등록된 상수들을 통해서 type-safe한 코드를 작성할 수 있다.
'📚 Spring > Spring REST' 카테고리의 다른 글
[Spring REST API #6] Bad Request (도메인 Validator를 통한 처리) (0) | 2020.07.31 |
---|---|
[Spring REST API #5] Bad Request 처리 (0) | 2020.07.30 |
[Spring REST API #4] Spring REST API Bad Request 처리 (0) | 2020.07.28 |
[Spring REST API #3] Spring REST API 입력값 제한 및 에러 발생 처리 (0) | 2020.07.27 |
REST API 란? (0) | 2020.06.20 |