From 7a8a2d96080188838c135ed409e50e2467cd9f05 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 25 Oct 2018 12:02:13 +0200 Subject: [PATCH] Fix HttpMessageWriter tests Issue: SPR-17419 --- .../codec/FormHttpMessageWriterTests.java | 20 +-- ...ServerSentEventHttpMessageWriterTests.java | 131 ++++++++++++------ .../reactive/test/MockServerHttpResponse.java | 9 +- 3 files changed, 107 insertions(+), 53 deletions(-) diff --git a/spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageWriterTests.java index f7a9627fa2b..c3f761467f7 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageWriterTests.java @@ -20,22 +20,22 @@ import java.util.Map; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; import org.springframework.core.ResolvableType; +import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author Sebastien Deleuze */ -public class FormHttpMessageWriterTests { +public class FormHttpMessageWriterTests extends AbstractDataBufferAllocatingTestCase { private final FormHttpMessageWriter writer = new FormHttpMessageWriter(); @@ -75,14 +75,18 @@ public class FormHttpMessageWriterTests { body.add("name 2", "value 2+1"); body.add("name 2", "value 2+2"); body.add("name 3", null); - MockServerHttpResponse response = new MockServerHttpResponse(); + MockServerHttpResponse response = new MockServerHttpResponse(this.bufferFactory); this.writer.write(Mono.just(body), null, MediaType.APPLICATION_FORM_URLENCODED, response, null).block(); - String responseBody = response.getBodyAsString().block(); - assertEquals("name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3", responseBody); + String expected = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3"; + StepVerifier.create(response.getBody()) + .consumeNextWith(stringConsumer( + expected)) + .expectComplete() + .verify(); HttpHeaders headers = response.getHeaders(); assertEquals("application/x-www-form-urlencoded;charset=UTF-8", headers.getContentType().toString()); - assertEquals(responseBody.getBytes().length, headers.getContentLength()); + assertEquals(expected.length(), headers.getContentLength()); } } diff --git a/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageWriterTests.java index 340ae2526f2..75f271f352f 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageWriterTests.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -31,6 +32,8 @@ import reactor.test.StepVerifier; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.MediaType; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @@ -45,6 +48,7 @@ import static org.springframework.core.ResolvableType.forClass; * @author Sebastien Deleuze * @author Rossen Stoyanchev */ +@SuppressWarnings("rawtypes") public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocatingTestCase { private static final Map HINTS = Collections.emptyMap(); @@ -52,6 +56,15 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll private ServerSentEventHttpMessageWriter messageWriter = new ServerSentEventHttpMessageWriter(new Jackson2JsonEncoder()); + private MockServerHttpResponse outputMessage; + + + @Before + public void setUp() { + this.outputMessage = new MockServerHttpResponse(this.bufferFactory); + } + + @Test public void canWrite() { @@ -72,41 +85,28 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll .comment("bla\nbla bla\nbla bla bla").retry(Duration.ofMillis(123L)).build(); Mono source = Mono.just(event); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, outputMessage, ServerSentEvent.class); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n") + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:")) + .consumeNextWith(stringConsumer("bar\n")) + .consumeNextWith(stringConsumer("\n")) .expectComplete() .verify(); } - @Test - @SuppressWarnings("rawtypes") - public void writeServerSentEventError() { - ServerSentEvent event = ServerSentEvent.builder().data("bar").id("c42").event("foo") - .comment("bla\nbla bla\nbla bla bla").retry(Duration.ofMillis(123L)).build(); - - Flux source = Flux.concat( - Flux.just(event), - Flux.error(new RuntimeException())); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); - - Mono result = this.messageWriter.write(source, forClass(ServerSentEvent.class), - MediaType.TEXT_EVENT_STREAM, outputMessage, HINTS); - - StepVerifier.create(result) - .verifyError(RuntimeException.class); - } - @Test public void writeString() { Flux source = Flux.just("foo", "bar"); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, outputMessage, String.class); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("data:foo\n\ndata:bar\n\n") + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("foo\n")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("bar\n")) + .consumeNextWith(stringConsumer("\n")) .expectComplete() .verify(); } @@ -114,11 +114,15 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll @Test public void writeMultiLineString() { Flux source = Flux.just("foo\nbar", "foo\nbaz"); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, outputMessage, String.class); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("data:foo\ndata:bar\n\ndata:foo\ndata:baz\n\n") + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("foo\ndata:bar\n")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("foo\ndata:baz\n")) + .consumeNextWith(stringConsumer("\n")) .expectComplete() .verify(); } @@ -128,22 +132,36 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll Flux source = Flux.just("\u00A3"); Charset charset = StandardCharsets.ISO_8859_1; MediaType mediaType = new MediaType("text", "event-stream", charset); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, mediaType, outputMessage, String.class); assertEquals(mediaType, outputMessage.getHeaders().getContentType()); - StepVerifier.create(outputMessage.getBodyAsString()).expectNext("data:\u00A3\n\n").verifyComplete(); + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(dataBuffer -> { + String value = + DataBufferTestUtils.dumpString(dataBuffer, charset); + DataBufferUtils.release(dataBuffer); + assertEquals("\u00A3\n", value); + }) + .consumeNextWith(stringConsumer("\n")) + .expectComplete() + .verify(); } @Test public void writePojo() { Flux source = Flux.just(new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar")); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, outputMessage, Pojo.class); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("data:{\"foo\":\"foofoo\",\"bar\":\"barbar\"}\n\n" + - "data:{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}\n\n") + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("\n")) .expectComplete() .verify(); } @@ -154,16 +172,21 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll this.messageWriter = new ServerSentEventHttpMessageWriter(new Jackson2JsonEncoder(mapper)); Flux source = Flux.just(new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar")); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, outputMessage, Pojo.class); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("data:{\n" + + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("{\n" + "data: \"foo\" : \"foofoo\",\n" + - "data: \"bar\" : \"barbar\"\n" + "data:}\n\n" + - "data:{\n" + + "data: \"bar\" : \"barbar\"\n" + "data:}")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("data:")) + .consumeNextWith(stringConsumer("{\n" + "data: \"foo\" : \"foofoofoo\",\n" + - "data: \"bar\" : \"barbarbar\"\n" + "data:}\n\n") + "data: \"bar\" : \"barbarbar\"\n" + "data:}")) + .consumeNextWith(stringConsumer("\n")) + .consumeNextWith(stringConsumer("\n")) .expectComplete() .verify(); } @@ -173,13 +196,35 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll Flux source = Flux.just(new Pojo("foo\uD834\uDD1E", "bar\uD834\uDD1E")); Charset charset = StandardCharsets.UTF_16LE; MediaType mediaType = new MediaType("text", "event-stream", charset); - MockServerHttpResponse outputMessage = new MockServerHttpResponse(); testWrite(source, mediaType, outputMessage, Pojo.class); assertEquals(mediaType, outputMessage.getHeaders().getContentType()); - StepVerifier.create(outputMessage.getBodyAsString()) - .expectNext("data:{\"foo\":\"foo\uD834\uDD1E\",\"bar\":\"bar\uD834\uDD1E\"}\n\n") - .verifyComplete(); + StepVerifier.create(outputMessage.getBody()) + .consumeNextWith(dataBuffer1 -> { + String value1 = + DataBufferTestUtils.dumpString(dataBuffer1, charset); + DataBufferUtils.release(dataBuffer1); + assertEquals("data:", value1); + }) + .consumeNextWith(dataBuffer -> { + String value = DataBufferTestUtils.dumpString(dataBuffer, charset); + DataBufferUtils.release(dataBuffer); + assertEquals("{\"foo\":\"foo\uD834\uDD1E\",\"bar\":\"bar\uD834\uDD1E\"}", value); + }) + .consumeNextWith(dataBuffer2 -> { + String value2 = + DataBufferTestUtils.dumpString(dataBuffer2, charset); + DataBufferUtils.release(dataBuffer2); + assertEquals("\n", value2); + }) + .consumeNextWith(dataBuffer3 -> { + String value3 = + DataBufferTestUtils.dumpString(dataBuffer3, charset); + DataBufferUtils.release(dataBuffer3); + assertEquals("\n", value3); + }) + .expectComplete() + .verify(); } diff --git a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java index 4aee940e787..0b45bdf0b9f 100644 --- a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java +++ b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -27,6 +27,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpHeaders; @@ -54,7 +55,11 @@ public class MockServerHttpResponse extends AbstractServerHttpResponse { public MockServerHttpResponse() { - super(new DefaultDataBufferFactory()); + this(new DefaultDataBufferFactory()); + } + + public MockServerHttpResponse(DataBufferFactory dataBufferFactory) { + super(dataBufferFactory); this.writeHandler = body -> { this.body = body.cache(); return this.body.then();