Loading...
Spring Framework Reference Documentation 7.0.2의 RestTestClient의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
RestTestClient은 서버 애플리케이션을 테스트하기 위해 설계된 HTTP 클라이언트입니다. 이는
Spring의 RestClient를 wrapping하고 이를 사용해 요청을 수행하지만,
응답을 검증하기 위한 테스트 파사드를 노출합니다. RestTestClient는
end-to-end HTTP 테스트를 수행하는 데 사용할 수 있습니다.
또한 MockMvc를 통해 실행 중인 서버 없이 Spring MVC 애플리케이션을 테스트하는 데에도 사용할 수 있습니다.
RestTestClient를 설정하려면 binding할 서버 설정을 선택해야 합니다. 이는 여러 MockMvc
설정 선택지 중 하나일 수도 있고, live 서버에 대한 연결일 수도 있습니다.
이 설정은 실행 중인 서버 없이 mock 요청과 응답 객체를 통해 특정 컨트롤러를 테스트할 수 있게 해줍니다.
1RestTestClient client = 2 RestTestClient.bindToController(new TestController()).build();
1val client = RestTestClient.bindToController(TestController()).build()
ApplicationContext이 설정은 Spring MVC 인프라스트럭처와 컨트롤러 선언이 포함된 Spring 설정을 로드하고, 실행 중인 서버 없이 mock 요청과 응답 객체를 통해 요청을 처리하는 데 사용할 수 있게 해줍니다.
1@SpringJUnitConfig(WebConfig.class) // (1) 2class MyTests { 3 4 RestTestClient client; 5 6 @BeforeEach 7 void setUp(ApplicationContext context) { // (2) 8 client = RestTestClient.bindToApplicationContext(context).build(); // (3) 9 } 10}
| 1 | 로드할 설정을 지정합니다 |
| 2 | 설정을 주입합니다 |
| 3 | RestTestClient를 생성합니다 |
1@SpringJUnitConfig(WebConfig::class) // (1) 2class MyTests { 3 4 lateinit var client: RestTestClient 5 6 @BeforeEach 7 fun setUp(context: ApplicationContext) { // (2) 8 client = RestTestClient.bindToApplicationContext(context).build() // (3) 9 } 10}
| 1 | 로드할 설정을 지정합니다 |
| 2 | 설정을 주입합니다 |
| 3 | RestTestClient를 생성합니다 |
이 설정은 실행 중인 서버 없이 mock 요청과 응답 객체를 통해 functional endpoint를 테스트할 수 있게 해줍니다.
1RouterFunction<?> route = ... 2client = RestTestClient.bindToRouterFunction(route).build();
1val route: RouterFunction<*> = ... 2val client = RestTestClient.bindToRouterFunction(route).build()
이 설정은 실행 중인 서버에 연결하여 완전한 end-to-end HTTP 테스트를 수행합니다:
1client = RestTestClient.bindToServer().baseUrl("http://localhost:8080").build();
1client = RestTestClient.bindToServer().baseUrl("http://localhost:8080").build()
앞에서 설명한 서버 설정 옵션 외에도, 기본 URL, 기본 헤더, 클라이언트 필터 등
여러 클라이언트 옵션을 설정할 수 있습니다. 이러한 옵션은 초기 bindTo 호출 이후에
바로 사용할 수 있으며, 다음과 같습니다:
1client = RestTestClient.bindToController(new TestController()) 2 .baseUrl("/test") 3 .build();
1client = RestTestClient.bindToController(TestController()) 2 .baseUrl("/test") 3 .build()
RestClient와 RestTestClient는
exchange() 호출 시점까지 동일한 API를 가집니다. 그 이후에는 RestTestClient가
응답을 검증하기 위한 두 가지 대체 방식을 제공합니다:
assertThat() 구문을 통해 응답을 검증하기 위한 AssertJ IntegrationBuilt-in assertion을 사용하려면 exchange() 호출 이후에도 워크플로 내에 머물면서
expectation 메서드 중 하나를 사용하면 됩니다. 예를 들면 다음과 같습니다:
1client.get().uri("/persons/1") 2 .accept(MediaType.APPLICATION_JSON) 3 .exchange() 4 .expectStatus().isOk() 5 .expectHeader().contentType(MediaType.APPLICATION_JSON);
1client.get().uri("/persons/1") 2 .accept(MediaType.APPLICATION_JSON) 3 .exchange() 4 .expectStatus().isOk() 5 .expectHeader().contentType(MediaType.APPLICATION_JSON)
모든 expectation이, 그 중 하나가 실패하더라도, 모두 assert되도록 하려면
여러 개의 체이닝된 expect*(..) 호출 대신 expectAll(..)을 사용할 수 있습니다. 이 기능은
AssertJ의 soft assertion 지원 및 JUnit Jupiter의 assertAll() 지원과 유사합니다.
1client.get().uri("/persons/1") 2 .accept(MediaType.APPLICATION_JSON) 3 .exchange() 4 .expectAll( 5 spec -> spec.expectStatus().isOk(), 6 spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON) 7 );
1client.get().uri("/persons/1") 2 .accept(MediaType.APPLICATION_JSON) 3 .exchange() 4 .expectAll( 5 { spec -> spec.expectStatus().isOk() }, 6 { spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON) } 7 )
그 다음에는 다음 중 하나를 통해 응답 본문을 디코딩할 수 있습니다:
expectBody(Class<T>): 단일 객체로 디코딩합니다.expectBody(): JSON Content 또는 비어 있는 본문에 대해 byte[]로 디코딩합니다.Built-in assertion이 충분하지 않은 경우, 대신 객체를 consume하고 다른 assertion을 수행할 수 있습니다:
1client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody(Person.class) 5 .consumeWith(result -> { 6 // custom assertions (for example, AssertJ)... 7 });
1client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody<Person>() 5 .consumeWith { 6 // custom assertions (for example, AssertJ)... 7 }
또는 워크플로를 종료하고 EntityExchangeResult를 얻을 수도 있습니다:
1EntityExchangeResult<Person> result = client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody(Person.class) 5 .returnResult();
1val result = client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody<Person>() 5 .returnResult()
제네릭이 포함된 대상 타입으로 디코딩해야 하는 경우, Class<T> 대신<br>ParameterizedTypeReference를 받는 오버로드된 메서드를 사용하십시오. |
응답에 콘텐츠가 없을 것으로 예상되는 경우, 다음과 같이 이를 assert할 수 있습니다:
1client.post().uri("/persons") 2 .body(person) 3 .exchange() 4 .expectStatus().isCreated() 5 .expectBody().isEmpty();
1client.post().uri("/persons") 2 .body(person) 3 .exchange() 4 .expectStatus().isCreated() 5 .expectBody().isEmpty()
응답 콘텐츠를 무시하려는 경우, 다음과 같이 아무 assertion 없이 콘텐츠를 해제할 수 있습니다:
1client.get().uri("/persons/123") 2 .exchange() 3 .expectStatus().isNotFound() 4 .expectBody(Void.class);
1client.get().uri("/persons/123") 2 .exchange() 3 .expectStatus().isNotFound() 4 .expectBody<Unit>()
대상 타입 없이 expectBody()를 사용하여 상위 수준 객체를 통해서가 아니라
raw 콘텐츠에 대해 assertion을 수행할 수 있습니다.
JSONAssert로 전체 JSON 콘텐츠를 검증하려면:
1client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody() 5 .json("{"name":"Jane"}")
1client.get().uri("/persons/1") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody() 5 .json("{"name":"Jane"}")
JSONPath로 JSON 콘텐츠를 검증하려면:
1client.get().uri("/persons") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody() 5 .jsonPath("$[0].name").isEqualTo("Jane") 6 .jsonPath("$[1].name").isEqualTo("Jason");
1client.get().uri("/persons") 2 .exchange() 3 .expectStatus().isOk() 4 .expectBody() 5 .jsonPath("$[0].name").isEqualTo("Jane") 6 .jsonPath("$[1].name").isEqualTo("Jason")
RestTestClientResponse는 AssertJ integration을 위한 주요 entry point입니다.
이는 exchange의 ResponseSpec을 wrapping하여 assertThat() 구문 사용을 가능하게 하는
AssertProvider입니다. 예를 들면 다음과 같습니다:
1ResponseSpec spec = client.get().uri("/persons").exchange(); 2 3RestTestClientResponse response = RestTestClientResponse.from(spec); 4assertThat(response).hasStatusOk(); 5assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN); 6// ...
1val spec = client.get().uri("/persons").exchange() 2 3val response = RestTestClientResponse.from(spec) 4assertThat(response).hasStatusOk() 5assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN) 6// ...
또한 먼저 built-in 워크플로를 사용한 다음, AssertJ와 함께 wrapping하여 계속 사용할
ExchangeResult를 얻을 수도 있습니다. 예를 들면 다음과 같습니다:
1ExchangeResult result = client.get().uri("/persons").exchange() 2 // ... 3 .returnResult(); 4 5RestTestClientResponse response = RestTestClientResponse.from(result); 6assertThat(response).hasStatusOk(); 7assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN); 8// ...
1val result = client.get().uri("/persons").exchange() 2 // ... 3 .returnResult() 4 5val response = RestTestClientResponse.from(result) 6assertThat(response).hasStatusOk() 7assertThat(response).hasContentTypeCompatibleWith(MediaType.TEXT_PLAIN) 8// ...
WebTestClient
MockMvc