일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- BFS
- Logback
- docker-compose
- Spring Cloud Config
- dp
- 백트래킹
- 스택
- Zuul
- 구현
- 게이트웨이
- spring boot
- 메모이제이션
- Java
- 구간 트리
- 서비스 디스커버리
- 트리
- 플로이드 와샬
- 주울
- 스프링 시큐리티
- 이분 매칭
- 이분 탐색
- 비트마스킹
- spring cloud
- ZuulFilter
- 달팽이
- 완전 탐색
- 도커
- 다익스트라
- Gradle
- 유레카
- Today
- Total
Hello, Freakin world!
[Spring] 컨트롤러 메서드 파리미터 JSON 바인딩 여부 테스트 본문
다음의 컨트롤러 계층의 메서드가 있다고 가정합니다.
@ToString
@NoArgsConstructor
@Getter
public class ItemCreateDto {
@NotNull
private String name;
@NotNull
private Integer price;
@NotNull
private Integer stockQuantity;
private List<ItemDetailDto> details;
}
@PostMapping("/items")
public String create(@RequestBody ItemCreateDto createDto) {
System.out.println(createDto);
return "created";
}
웹 POST 요청 바디의 JSON객체가 ItemCreateDto에 제대로 바인딩되는지 확인하고 싶습니다.
간단한 방법은 create 메서드에 println 과 같은 메서드를 추가해 콘솔에서 확인하는 겁니다. 간단하긴 하지만 영구적인 테스트 케이스를 만들기는 무리가 있습니다. create 메서드에 부작용이 추가되기도 하고 자동화된 테스트를 수행할 수도 없습니다.
테스트하기에 앞서 @RequestBody에 대해서 살펴봅시다.
메스드 파라미터 앞에 사용되어 요청 바디가 여기에 바인딩 될것이다~ 라고 마킹하는 용도의 애너테이션입니다.
요청 바디의 데이터가 파리미터에 전달되기 전에 HttpMessageConverter를 거친다고 하네요.
HttpMessageConverters 도 살펴봅시다.
HttpMessageConverters는 HttpMessageConverter들을 모아놓은 편의 클래스입니다.
실제 런타임에 등록된 컨터버들을 확인해볼까요?
@SpringBootTest
public class ItemRestControllerTest {
@Autowired
private HttpMessageConverters converters;
@Test
public void notNull() {
assertThat(converters).isNotNull();
converters.getConverters().stream()
.forEach(c -> System.out.println(c.getClass()));
}
}
class org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration$ResourceSupportHttpMessageConverter
class org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration$ResourceSupportHttpMessageConverter
class org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter
class org.springframework.http.converter.ByteArrayHttpMessageConverter
class org.springframework.http.converter.StringHttpMessageConverter
class org.springframework.http.converter.StringHttpMessageConverter
class org.springframework.http.converter.ResourceHttpMessageConverter
class org.springframework.http.converter.ResourceRegionHttpMessageConverter
class org.springframework.http.converter.xml.SourceHttpMessageConverter
class org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
class org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
class org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter
class org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
class org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
위와 같은 컨버터들이 등록되어 사용된다는 걸 알 수 있습니다.
우리는 JSON 객체의 바인딩에 관심있으므로 관련 클래스를 살펴봅시다. MappingJackson2HttpMessageConverter 가 보이네요. @RequestBody를 이용해 JSON 데이터를 객체에 바인딩할 때 MappingJackson2HttpMessageConverter 객체가 사용됩니다.(사실 구글 검색을 통해서 확인할 수도 있습니다)
MappingJackson2HttpMessageConverter가 사용된다는 걸 알았으니 전체 MVC 흐름 위에서 테스트를 작성하는게 아닌, 고립된 범위에서 테스트를 작성할 수 있을 것 같습니다.
@Test
public void create_파라미터_바인딩테스트() throws Exception {
List<ItemDetailDto> details = new ArrayList<>();
details.add(new ItemDetailDto("tag","content"));
ItemCreateDto createDto = ItemCreateDto.builder()
.name("name")
.price(1000)
.stockQuantity(1000)
.details(details).build();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(new ObjectMapper());
Object ret = converter.read(ItemCreateDto.class, new MockHttpInputMessage(gson.toJson(createDto).getBytes()));
ItemCreateDto bindedDto = (ItemCreateDto) ret;
assertThat(bindedDto.getName()).isEqualTo("name");
assertThat(bindedDto.getPrice()).isEqualTo(1000);
assertThat(bindedDto.getStockQuantity()).isEqualTo(1000);
assertThat(bindedDto.getDetails()).isEqualTo(details);
}
MappingJackson2HttpMessageConverter api는 ObjectMapper와 유사합니다. ObjectMapper 관련글을 참고하세요.
또 하나의 특이사항은 MockHttpInputMessage를 사용해 mock http 메세지를 만든 점입니다.
실제로 요청을 날려 돌아가는지 확인해볼까요?
'Spring boot' 카테고리의 다른 글
[Spring boot]도커 컴포즈로 서비스 클러스터 구성하기 (0) | 2021.03.03 |
---|---|
[Spring AOP] 포인트컷의 종류와 성능 (0) | 2020.07.24 |
Spring AOP 기반 validation 수행하기 (0) | 2020.07.24 |
[Spring AOP] 포인트컷 지시어들(Designators) (0) | 2020.07.18 |
[Spring AOP] 포인트컷 선언하기 (0) | 2020.07.18 |