카테고리 없음

TestRestTemplate - postForEntity() / ResponseEntity

kjyyjk 2023. 3. 25. 19:50

 학습 내용 

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 에 대한 지식이 부족하기 때문이기에 나중에 따로 공부해봐야겠다.

 

 


참고