RestApi 만들기 - Repository추가하기 (2)

반응형
반응형

c accept,content에 대해 무지했던것 같다.

    @Test
    void create_Delivery() throws Exception {
        Delivery delivery = Delivery.builder()
                .id(10)
                .item("book")
                .user("klom")
                .build();
        mockMvc.perform(post("/api/delivery/")
                    .accept(MediaTypes.HAL_JSON_VALUE)
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(objectMapper.writeValueAsString(delivery))
                )
               .andDo(print())
               .andExpect(status().isCreated());
    }

코드를 이렇게 수정했다.
현재 코드는 모든 MediaTypes를 허용하기 때문에 성공하게 된다.

@RequestMapping(value = "/api/delivery" ,produces = MediaTypes.HAL_JSON_VALUE)

근데 여기서 드는 의문점은 이것을 넣지 않는다면 어떤식으로 나오는지 궁금해졌다.

컨트롤러, 테스트 둘다 없는 경우

MockHttpServletRequest:
	  요청
      HTTP Method = POST
      Request URI = /api/delivery/
       Parameters = {}
          Headers = [Content-Length:"94"]
             Body = {"id":10,"item":"book","user":"klom","deliveryTime":null,"deliveryEndTime":null,"status":null}
    Session Attrs = {}
    
MockHttpServletResponse:
			응답
           Status = 201
    Error message = null
          Headers = [Location:"http://localhost/api/delivery/%257Bid%257D", Content-Type:"application/json"]
     Content type = application/json
             Body = {"id":10,"item":null,"user":null,"deliveryTime":null,"deliveryEndTime":null,"status":null}
    Forwarded URL = null
   Redirected URL = http://localhost/api/delivery/%257Bid%257D
          Cookies = []    

아직까지는 다른것이 확인이 되지 않는다.

컨트롤러에만 있는 경우

MockHttpServletRequest:
	 요청
      HTTP Method = POST
      Request URI = /api/delivery/
       Parameters = {}
          Headers = [Content-Length:"94"]
             Body = {"id":10,"item":"book","user":"klom","deliveryTime":null,"deliveryEndTime":null,"status":null}
    Session Attrs = {}
    
MockHttpServletResponse:
		응답
           Status = 201
    Error message = null
          Headers = [Location:"http://localhost/api/delivery/%257Bid%257D", Content-Type:"application/hal+json"]
     Content type = application/hal+json
             Body = {"id":10,"item":null,"user":null,"deliveryTime":null,"deliveryEndTime":null,"status":null}
    Forwarded URL = null
   Redirected URL = http://localhost/api/delivery/%257Bid%257D
          Cookies = []    

content type을 주목해보면 변경이 된것을 확인 할 수 있다.

테스트에만 있는 경우

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /api/delivery/
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/hal+json", Content-Length:"94"]
             Body = {"id":10,"item":"book","user":"klom","deliveryTime":null,"deliveryEndTime":null,"status":null}
    Session Attrs = {}
    
MockHttpServletResponse:
           Status = 201
    Error message = null
          Headers = [Location:"http://localhost/api/delivery/%257Bid%257D", Content-Type:"application/hal+json"]
     Content type = application/hal+json
             Body = {"id":10,"item":null,"user":null,"deliveryTime":null,"deliveryEndTime":null,"status":null}
    Forwarded URL = null
   Redirected URL = http://localhost/api/delivery/%257Bid%257D
          Cookies = []    

content-type이 서로 다르다는 것을 확인 할 수 있다.

이것을 다시 생각해보면

컨트롤러에서 특정 요청을 요청한다.
그러면 그것을 테스트에서 요청될것이 작성되어지는데,
컨트롤러는 그 요청을 받아서 응답으로 만들어준다.

즉, 컨트롤러 -> 테스트 -> 컨트롤러 순으로 진행된다고 생각하면 될것 같다.
아무리 위에서 에러가 나지 않는다고 해도 요청과 응답을 서로 일치해주는게 좋은 방법이라 생각한다.
나중에 대처하려 하면 눈덩이 처럼 불어나서 못할지도 모른다.

그래서 이번에는 이렇게 수정했다.

전부 있는 경우

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /api/delivery/
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/hal+json", Content-Length:"94"]
             Body = {"id":10,"item":"book","user":"klom","deliveryTime":null,"deliveryEndTime":null,"status":null}
    Session Attrs = {}
    
    MockHttpServletResponse:
           Status = 201
    Error message = null
          Headers = [Location:"http://localhost/api/delivery/%257Bid%257D", Content-Type:"application/hal+json"]
     Content type = application/hal+json
             Body = {"id":10,"item":null,"user":null,"deliveryTime":null,"deliveryEndTime":null,"status":null}
    Forwarded URL = null
   Redirected URL = http://localhost/api/delivery/%257Bid%257D
          Cookies = []

확인결과 서로 일치한다는 것을 확인 할 수 있었다.

이제 본격적으로 시작해보자.
생각해보면 db가 추가된다면 어떻게 될지 상상해봤다.

이러한 컴파일에러가 생겼다는건 아직 만들지 않았다는 이야기다.
만들어 보자.

생성후 이대로 실행해보니 다음과 같은 에러가 발생했다.

이러한 이유가 나오는 결정적인 이유는 
현재 webMvcTest로 되어있기 때문이다.
이것이 왜 중요하나 그 이유는 이 테스트는 슬라이싱 테스트라는 뜻이다.
슬라이싱 테스트라는 해당 조각만 테스트가 가능하는 뜻으로,
여기에서는 web관련 테스트만 가능하다는 뜻이된다.

하지만 아쉽게도 Repository는 web관련 설정이 아니다. |
여러가지 방법이 존재하겠지만,
간단히 하는 방법은

MockBean으로 주입받는 것이다.
즉, 이것을 가상으로 빈으로 만들준다는 거다.

@MockBean
private DeliveryRepository deliveryRepository;

이제 deliveryRepository를 사용해보자.

이렇게 사용하면 될까?

Delivery newDelivery = deliveryRepository.save(delivery);

물론 이 방법도 틀린 방법은 아니다. 하지만 이 코드의 가장 큰 문제점은 굳이 이러한 코드를 테스트에 작성해야 되나는 것이다.
그렇다면 어떻게 해야될까?

만약에 save가 될때 delivery가 리턴이 된다고 한다면?

이런것이 더 테스트에 어울리지 않을까?

Mockito.when(deliveryRepository.save(any(Delivery.class))).thenReturn(delivery);

when : 어떠한 행동을 한다면,
다음을 리턴한다.

아쉽게도 에러가 나오지 않는다.

그래서 어쩔 수 없이 컨트롤러의 코드를 수정하자.

Delivery newDelivery = deliveryRepository.save(deliver);
URI createUri = linkTo(DeliveryController.class).slash(newDelivery.getId()).toUri();

이제 부터는 세이브한 객체의 아이디로 받아서 그것을 사용하는 코드로 만들었다.

그 결과는

성공이다.

 

반응형

댓글

Designed by JB FACTORY