♪ 학습 내용
PostAPIController Test code 작성 중 새로 접한 TestRestTemplate과 그의 메서드 postForEntity(), 그리고 연속적으로 ResponseEntity<T> 에 관해 학습
* TestRestTemplate과의 첫 만남
[스프링부트와 AWS로 혼자 구현하는 웹 서비스] 서적으로 학습하던 중,
아래와 같이 Controller Test Code를 작성.
@Autowired
private TestRestTemplate restTemplate;
@Test
public void Posts_등록된다() throws Exception{
... 생략 ...
String url = "http://localhost:" + port + "/api/v1/posts";
//when
ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url, requestDto, Long.class);
//then
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(responseEntity.getBody()).isGreaterThan(0L);
... 생략 ....
}
단위 테스트의 TestRestTemlate.postForEntity()에서 Mapping될 URL과 저장될 객체, 그리고 타입을 넘긴 후 반환된 결과로 로직이 잘 수행되었는가 확인하는 것을 보고,
실제 서버에 전송하듯이 해당 URL을 호출하고 객체를 넘겨 결과를 반환 받는 것인가? 라고 생각.
* TestRestTemplate vs MockMvc
이전에 테스트 코드 작성 시 MockMvc를 이용하여 작성했었다.
하지만 이번에는 TestRestTemplate을 이용하여 작성. 무슨 차이?
! MockMvc는 서블릿 컨테이너를 사용하지 않지만, TestRestTemplate은 서블릿 컨테이너를 사용
! MockMvc는 서버 입장에서 테스트를 수행, TestRestTemplate은 클라이언트 입장에서 테스트를 수행
https://meetup.nhncloud.com/posts/124
* TestRestTemplate
REST 방식으로 개발한 API의 Test를 최적화 하기 위해 만들어진 클래스이고,
기능적인 면에서 보면 HTTP 요청과 그 결과를 반환해준다.
- 주로 사용되는 TestRestTemplate의 메서드들
https://easybrother0103.tistory.com/64
추가적으로,
Spring 공식 문서에서 postForEntity()에 대한 정보를 찾아보았다.
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType)
! 주어진 request 객체를 url에 Post하여 새로운 Resouce를 생성하고, 응답 결과를 ResponseEntity로 받는다.
! Class<T> 는 반환 값의 타입이다.
ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url, requestDto, Long.class);
해당 코드에서는 requestDto 객체를 url에 Post 요청. 반환 값의 타입은 Long. 결과로 ResponseEntity를 반환받는다.
하나 의문이 들었던 것은 왜 Long 일까? 였다..
이건 ResponseEntity의 getStatusCode() 메서드이다.
/**
* Return the HTTP status code of the response.
* @return the HTTP status as an HttpStatus enum entry
*/
public HttpStatus getStatusCode() {
if (this.status instanceof HttpStatus) {
return (HttpStatus) this.status;
}
else {
return HttpStatus.valueOf((Integer) this.status);
}
}
! 응답의 상태 코드 반환
이것만 봐서는 왜 Long 인지 알 수 가 없었는데
/**
* Returns the body of this entity.
*/
@Nullable
public T getBody() {
return this.body;
}
HttpEntity<T> 의 메서드인 getBody() 메서드에서 T타입의 body를 반환하는 것을 보고 깨달았다.
(ResponseEntity는 HttpEntity를 상속받는다)
- 테스트의 대상인 Controller 코드
@PostMapping("/api/v1/posts")
public Long save(@RequestBody PostsSaveRequestDto requestDto){
return postsService.save(requestDto);
}
! 해당 url을 호출하면 다음 메서드가 매핑되고, 그 반환 값으로 Long타입을 반환한다.
Long타입 반환 값은 실질적으로 전송의 목적이 되는 데이터이고 HttpBody에 들어가게 된다.
그리고 RequestEntity는 Http헤더와 Http바디를 포함하는 클래스.
따라서 body에 들어갈 데이터 타입이 Long이기 때문에
postForEntity()에서 Long.class로, ResponseEnity<Long>을 반환 받은 것.
' ResponseEntity는 사용자의 HttpRequest에 대한 응답하는 데이터를 가진다.
Http Status, Header, Body를 포함한다. '
누가 보면 당연한 것이겠지만, 현재의 나로써는 이렇게 하나하나 찾아가며 했어야 이해가 가는..
이는 HttpEntity와 ResponseEntity 에 대한 지식이 부족하기 때문이기에 나중에 따로 공부해봐야겠다.
참고
- https://easybrother0103.tistory.com/64
- https://meetup.nhncloud.com/posts/124
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/web/client/TestRestTemplate.html#postForEntity(java.net.URI,java.lang.Object,java.lang.Class)
- https://blog.naver.com/PostView.naver?blogId=mijosan&logNo=222198041845&parentCategoryNo=&categoryNo=46&viewDate=&isShowPopularPosts=false&from=postView
- https://www.inflearn.com/blogs/339
- https://wedul.site/446
- https://velog.io/@chaewss/Spring-Boot-RestController-ResponseEntity%EB%9E%80
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!