/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.test.web.reactive.server.samples; import java.net.URI; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.test.web.reactive.server.FluxExchangeResult; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import static java.time.Duration.ofMillis; import static org.hamcrest.CoreMatchers.endsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.springframework.core.ResolvableType.forClassWithGenerics; import static org.springframework.http.MediaType.TEXT_EVENT_STREAM; /** * Annotated controllers accepting and returning typed Objects. * * @author Rossen Stoyanchev * @since 5.0 */ public class ResponseEntityTests { private final WebTestClient client = WebTestClient.bindToController(new PersonController()).build(); @Test public void entity() throws Exception { this.client.get().uri("/persons/John") .exchange() .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8) .expectBody(Person.class).isEqualTo(new Person("John")); } @Test public void entityWithConsumer() throws Exception { this.client.get().uri("/persons/John") .exchange() .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8) .expectBody(Person.class).consumeWith(p -> assertEquals(new Person("John"), p)); } @Test public void entityList() throws Exception { List<Person> expected = Arrays.asList( new Person("Jane"), new Person("Jason"), new Person("John")); this.client.get().uri("/persons") .exchange() .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8) .expectBodyList(Person.class).isEqualTo(expected); } @Test public void entityMap() throws Exception { Map<String, Person> map = new LinkedHashMap<>(); map.put("Jane", new Person("Jane")); map.put("Jason", new Person("Jason")); map.put("John", new Person("John")); this.client.get().uri("/persons?map=true") .exchange() .expectStatus().isOk() .expectBody(forClassWithGenerics(Map.class, String.class, Person.class)).isEqualTo(map); } @Test public void entityStream() throws Exception { FluxExchangeResult<Person> result = this.client.get() .uri("/persons") .accept(TEXT_EVENT_STREAM) .exchange() .expectStatus().isOk() .expectHeader().contentType(TEXT_EVENT_STREAM) .returnResult(Person.class); StepVerifier.create(result.getResponseBody()) .expectNext(new Person("N0"), new Person("N1"), new Person("N2")) .expectNextCount(4) .consumeNextWith(person -> assertThat(person.getName(), endsWith("7"))) .thenCancel() .verify(); } @Test public void postEntity() throws Exception { this.client.post().uri("/persons") .syncBody(new Person("John")) .exchange() .expectStatus().isCreated() .expectHeader().valueEquals("location", "/persons/John") .expectBody().isEmpty(); } @RestController @RequestMapping("/persons") static class PersonController { @GetMapping("/{name}") Person getPerson(@PathVariable String name) { return new Person(name); } @GetMapping Flux<Person> getPersons() { return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John")); } @GetMapping(params = "map") Map<String, Person> getPersonsAsMap() { Map<String, Person> map = new LinkedHashMap<>(); map.put("Jane", new Person("Jane")); map.put("Jason", new Person("Jason")); map.put("John", new Person("John")); return map; } @GetMapping(produces = "text/event-stream") Flux<Person> getPersonStream() { return Flux.interval(ofMillis(100)).onBackpressureBuffer(10).map(index -> new Person("N" + index)); } @PostMapping ResponseEntity<String> savePerson(@RequestBody Person person) { return ResponseEntity.created(URI.create("/persons/" + person.getName())).build(); } } }