테스트 케이스는 다음과 같다.
고려 사항
package com.carrykim.restapi.event;
import com.carrykim.restapi.event.model.dto.EventDto;
import com.fasterxml.jackson.databind.ObjectMapper;
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.hateoas.MediaTypes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
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.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@SpringBootTest
@AutoConfigureMockMvc
public class EventControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
private EventDto createEventDto(){
return EventDto.builder()
.name("My Event")
.description("This is my first Event")
.build();
}
@Test
public void create_event_success() throws Exception {
//Given
EventDto eventDto = createEventDto();
//When
//Then
mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaTypes.HAL_JSON)
.content(objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("id").exists())
.andExpect(header().exists(HttpHeaders.LOCATION))
.andExpect(header().string(HttpHeaders.CONTENT_TYPE,MediaTypes.HAL_JSON_VALUE));
}
@Test
public void create_event_bad_request_empty_input() throws Exception {
//Given
EventDto eventDto = EventDto.builder().build();
//When
//Then
mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(jsonPath("timestamp").exists())
.andExpect(jsonPath("status").exists())
.andExpect(jsonPath("error").exists())
.andExpect(jsonPath("message").exists());
}
}
package com.carrykim.restapi.event.controller;
import com.carrykim.restapi.event.model.Event;
import com.carrykim.restapi.event.infra.EventRepository;
import com.carrykim.restapi.event.model.dto.EventDto;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.net.URI;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@RestController()
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE)
public class EventController {
private final EventRepository eventRepository;
public EventController(EventRepository eventRepository) {
this.eventRepository = eventRepository;
}
@PostMapping("")
public ResponseEntity create(@RequestBody @Valid EventDto eventDto) {
Event newEvent = this.eventRepository.save(eventDto.toModel());
URI uri = linkTo(methodOn(EventController.class).create(new EventDto())).slash(newEvent.getId()).toUri();
return ResponseEntity.created(uri).body(newEvent);
}
}
package com.carrykim.restapi.event.global.exception;
import lombok.Builder;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Getter
public class ErrorResponse {
private final LocalDateTime timestamp = LocalDateTime.now();
private int status;
private List<String> message;
private String error;
public ErrorResponse(HttpStatus httpStatus , BindingResult bindingResult) {
this.status = httpStatus.value();
this.error = httpStatus.name();
this.message = bindingResult.getFieldErrors().stream()
.map(e -> {
String m = e.getField() + " : " + e.getDefaultMessage();
return m;
})
.collect(Collectors.toList());
}
}
package com.carrykim.restapi.event.global.exception;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class EventExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity validationErrorException(final MethodArgumentNotValidException e) throws JsonProcessingException {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(new ErrorResponse(HttpStatus.BAD_REQUEST,e.getBindingResult()));
}
}