Loading...
Spring Framework Reference Documentation 7.0.2의 Testing Client Applications의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
RestClient 또는 RestTemplate을 사용하는 코드를 테스트하려면
OkHttp MockWebServer 또는
WireMock과 같은 mock 웹 서버를 사용할 수 있습니다. Mock 웹 서버는 일반적인 서버처럼 HTTP를 통해 요청을 수락하며, 이는 프로덕션에서와 동일한 방식으로 구성된 동일한 HTTP 클라이언트로 테스트할 수 있음을 의미합니다. 이는 서로 다른 클라이언트가 네트워크 I/O를 처리하는 방식에 종종 미묘한 차이가 있기 때문에 중요합니다.
Mock 웹 서버의 또 다른 장점은 프로덕션에서 사용하는 클라이언트와 결합하여 전송 레벨에서 특정 네트워크 이슈 및 조건을 시뮬레이트할 수 있는 능력입니다.
전용 mock 웹 서버 외에도, 역사적으로 Spring Framework는 MockRestServiceServer를 통해 RestClient 또는 RestTemplate을 테스트하기 위한 내장 옵션을 제공해 왔습니다.
이는 테스트 대상 클라이언트를 mock 서버에 의해 지원되는 커스텀 ClientHttpRequestFactory로 구성하는 데 의존하며, mock 서버는 요청을 예상하고 “stub” 응답을 보내도록 설정되어 있으므로, 서버를 실행하지 않고도 코드를 고립 상태에서 테스트하는 데 집중할 수 있습니다.
MockRestServiceServer는 mock 웹 서버의 존재 이전에 만들어졌습니다. 현재로서는 전송 계층과 네트워크 조건을 보다 완전하게 테스트하기 위해 mock 웹 서버를 사용할 것을<br>권장합니다.
다음 예제는 MockRestServiceServer를 사용하는 예를 보여줍니다:
1RestTemplate restTemplate = new RestTemplate(); 2 3MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build(); 4mockServer.expect(requestTo("/greeting")).andRespond(withSuccess()); 5 6// Test code that uses the above RestTemplate ... 7 8mockServer.verify();
1val restTemplate = RestTemplate() 2 3val mockServer = MockRestServiceServer.bindTo(restTemplate).build() 4mockServer.expect(requestTo("/greeting")).andRespond(withSuccess()) 5 6// Test code that uses the above RestTemplate ... 7 8mockServer.verify()
앞선 예제에서 클라이언트 사이드 REST 테스트를 위한 중앙 클래스인 MockRestServiceServer는
실제 요청을 기대값에 대해 어서트하고 “stub” 응답을 반환하는 커스텀 ClientHttpRequestFactory로 RestTemplate을 구성합니다. 이 경우, 우리는 /greeting에 대한 요청을 예상하고 text/plain 콘텐츠를 가진 200 응답을 반환하기를 원합니다. 필요에 따라 추가적인 예상 요청과 stub 응답을 정의할 수 있습니다.
예상 요청과 stub 응답을 정의하면, RestTemplate은 평소와 같이 클라이언트 사이드 코드에서 사용할 수 있습니다. 테스트의 끝에서 mockServer.verify()를 사용하여 모든 기대값이 충족되었는지 확인할 수 있습니다.
기본적으로 요청은 기대값이 선언된 순서대로 예상됩니다. 서버를 빌드할 때 ignoreExpectOrder 옵션을 설정할 수 있으며, 이 경우 주어진 요청에 대한 매치를 찾기 위해 모든 기대값이 (순서대로) 확인됩니다. 이는 요청이 어떤 순서로든 들어올 수 있음을 의미합니다. 다음 예제는 ignoreExpectOrder를 사용합니다:
1server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
1server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build()
기본적으로 순서 없는 요청일지라도 각 요청은 한 번만 실행될 수 있습니다.
expect 메서드는 count 범위(예: once, manyTimes, max, min,
between 등)를 지정하는 ExpectedCount 인수를 받는 오버로드된 변형을 제공합니다.
다음 예제는 times를 사용합니다:
1RestTemplate restTemplate = new RestTemplate(); 2 3MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build(); 4mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess()); 5mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess()); 6 7// ... 8 9mockServer.verify();
1val restTemplate = RestTemplate() 2 3val mockServer = MockRestServiceServer.bindTo(restTemplate).build() 4mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess()) 5mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess()) 6 7// ... 8 9mockServer.verify()
ignoreExpectOrder가 설정되지 않은 경우(기본값) 요청은 선언 순서대로 예상되며, 따라서 그 순서는 어떤 예상 요청의 첫 번째에만 적용된다는 점에 유의하십시오. 예를 들어 "/something"이 두 번, 그 뒤에 "/somewhere"가 세 번 예상되는 경우, "/somewhere"에 대한 요청이 있기 전에 "/something"에 대한 요청이 하나 있어야 하지만, 그 이후의 "/something"과 "/somewhere" 요청은 언제든지 올 수 있습니다.
위의 모든 것에 대한 대안으로, 클라이언트 사이드 테스트 지원은 RestTemplate에 구성하여 이를 MockMvc 인스턴스에 바인딩할 수 있는 ClientHttpRequestFactory 구현도 제공합니다. 이를 통해 서버를 실행하지 않고도 실제 서버 사이드 로직을 사용하여 요청을 처리할 수 있습니다. 다음 예제는 그 방법을 보여줍니다:
1MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 2this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc)); 3 4// Test code that uses the above RestTemplate ...
1val mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build() 2restTemplate = RestTemplate(MockMvcClientHttpRequestFactory(mockMvc)) 3 4// Test code that uses the above RestTemplate ...
일부 경우에는 응답을 mocking하는 대신 원격 서비스에 대한 실제 호출을 수행해야 할 필요가 있을 수 있습니다. 다음 예제는 ExecutingResponseCreator를 통해 이를 수행하는 방법을 보여줍니다:
1RestTemplate restTemplate = new RestTemplate(); 2 3// Create ExecutingResponseCreator with the original request factory 4ExecutingResponseCreator withActualResponse = new ExecutingResponseCreator(restTemplate.getRequestFactory()); 5 6MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build(); 7mockServer.expect(requestTo("/profile")).andRespond(withSuccess()); 8mockServer.expect(requestTo("/quoteOfTheDay")).andRespond(withActualResponse); 9 10// Test code that uses the above RestTemplate ... 11 12mockServer.verify();
1val restTemplate = RestTemplate() 2 3// Create ExecutingResponseCreator with the original request factory 4val withActualResponse = ExecutingResponseCreator(restTemplate.getRequestFactory()) 5 6val mockServer = MockRestServiceServer.bindTo(restTemplate).build() 7mockServer.expect(requestTo("/profile")).andRespond(withSuccess()) 8mockServer.expect(requestTo("/quoteOfTheDay")).andRespond(withActualResponse) 9 10// Test code that uses the above RestTemplate ... 11 12mockServer.verify()
앞선 예제에서 우리는 MockRestServiceServer가 응답을 mocking하는 다른 ClientHttpRequestFactory로 교체하기 전에 RestTemplate에서 ClientHttpRequestFactory를 사용하여 ExecutingResponseCreator를 생성합니다.
그런 다음 두 가지 종류의 응답에 대한 기대값을 정의합니다:
/profile 엔드포인트에 대한 stub 200 응답 (실제 요청은 실행되지 않음)/quoteOfTheDay 엔드포인트 호출을 통해 얻은 응답두 번째 경우, 요청은 이전에 캡처된 ClientHttpRequestFactory를 통해 실행됩니다. 이는 예를 들어, RestTemplate이 원래 어떻게 구성되었는지에 따라 실제 원격 서버에서 올 수도 있는 응답을 생성합니다.
서버 사이드 테스트와 마찬가지로, 클라이언트 사이드 테스트를 위한 플루언트 API에는 몇 가지 static import가 필요합니다. 이는 MockRest*을 검색하여 쉽게 찾을 수 있습니다. Eclipse 사용자는 Eclipse 환경설정의 Java → Editor → Content Assist → Favorites에서 MockRestRequestMatchers.* 및 MockRestResponseCreators.*를 “favorite static members”로 추가해야 합니다.
이렇게 하면 static 메서드 이름의 첫 글자를 입력한 후 content assist를 사용할 수 있습니다. 다른 IDE(IntelliJ 등)는 추가 구성이 필요하지 않을 수 있습니다. Static 멤버에 대한 코드 완성 지원을 확인하십시오.
Spring MVC Test 자체의 테스트에는 클라이언트 사이드 REST 테스트의 example tests가 포함되어 있습니다.
Further Examples
Appendix