diff --git a/build.gradle b/build.gradle index 98222b6c21..dbd62d9914 100644 --- a/build.gradle +++ b/build.gradle @@ -170,6 +170,7 @@ configure(allprojects) { project -> } repositories { + mavenLocal() maven { url "https://repo.spring.io/libs-release" } maven { url "https://repo.spring.io/milestone" } maven { url "https://repo.spring.io/snapshot" } // Reactor 3 snapshots @@ -396,6 +397,7 @@ project("spring-core") { optional "io.reactivex.rxjava2:rxjava:${rxjava2Version}" optional "io.reactivex:rxjava-reactive-streams:${rxjavaAdapterVersion}" optional("io.netty:netty-buffer:${nettyVersion}") + testCompile("io.projectreactor.addons:reactor-test:1.0.0.BUILD-SNAPSHOT") testCompile("javax.xml.bind:jaxb-api:${jaxbVersion}") testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}") testCompile("org.xmlunit:xmlunit-matchers:${xmlunitVersion}") @@ -776,6 +778,7 @@ project("spring-web") { optional("javax.xml.ws:jaxws-api:${jaxwsVersion}") optional("javax.mail:javax.mail-api:${javamailVersion}") testCompile(project(":spring-context-support")) // for JafMediaTypeFactory + testCompile("io.projectreactor.addons:reactor-test:1.0.0.BUILD-SNAPSHOT") testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") { exclude group: "org.apache.taglibs", module: "taglibs-standard-spec" } @@ -817,6 +820,7 @@ project("spring-web-reactive") { optional("org.freemarker:freemarker:${freemarkerVersion}") optional "org.apache.httpcomponents:httpclient:${httpclientVersion}" optional('org.webjars:webjars-locator:0.32') + testCompile("io.projectreactor.addons:reactor-test:1.0.0.BUILD-SNAPSHOT") testCompile("javax.validation:validation-api:${beanvalVersion}") testCompile("org.hibernate:hibernate-validator:${hibval5Version}") testCompile("javax.el:javax.el-api:${elApiVersion}") diff --git a/spring-core/src/test/java/org/springframework/core/codec/ByteArrayDecoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ByteArrayDecoderTests.java index 0994605af7..ec31eca002 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ByteArrayDecoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ByteArrayDecoderTests.java @@ -21,11 +21,11 @@ import java.util.Collections; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertArrayEquals; @@ -57,12 +57,12 @@ public class ByteArrayDecoderTests extends AbstractDataBufferAllocatingTestCase Flux output = this.decoder.decode(source, ResolvableType.forClassWithGenerics(Publisher.class, byte[].class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValuesWith(bytes -> assertArrayEquals("foo".getBytes(), bytes), - bytes -> assertArrayEquals("bar".getBytes(), bytes)); + ScriptedSubscriber + .create() + .consumeNextWith(bytes -> assertArrayEquals("foo".getBytes(), bytes)) + .consumeNextWith(bytes -> assertArrayEquals("bar".getBytes(), bytes)) + .expectComplete() + .verify(output); } } \ No newline at end of file diff --git a/spring-core/src/test/java/org/springframework/core/codec/ByteArrayEncoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ByteArrayEncoderTests.java index c4f822ff46..cb4ccbf6cb 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ByteArrayEncoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ByteArrayEncoderTests.java @@ -24,11 +24,11 @@ import org.junit.Before; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertArrayEquals; @@ -66,17 +66,20 @@ public class ByteArrayEncoderTests extends AbstractDataBufferAllocatingTestCase Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClassWithGenerics(Publisher.class, ByteBuffer.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertValuesWith(b -> { + ScriptedSubscriber + .create() + .consumeNextWith(b -> { byte[] buf = new byte[3]; b.read(buf); assertArrayEquals(fooBytes, buf); - }, b -> { + }) + .consumeNextWith(b -> { byte[] buf = new byte[3]; b.read(buf); assertArrayEquals(barBytes, buf); - }); + }) + .expectComplete() + .verify(output); } } diff --git a/spring-core/src/test/java/org/springframework/core/codec/ByteBufferDecoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ByteBufferDecoderTests.java index 6511c21562..61af89af5d 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ByteBufferDecoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ByteBufferDecoderTests.java @@ -22,11 +22,11 @@ import java.util.Collections; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertFalse; @@ -57,10 +57,10 @@ public class ByteBufferDecoderTests extends AbstractDataBufferAllocatingTestCase Flux output = this.decoder.decode(source, ResolvableType.forClassWithGenerics(Publisher.class, ByteBuffer.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValues(ByteBuffer.wrap("foo".getBytes()), ByteBuffer.wrap("bar".getBytes())); + + ScriptedSubscriber.create() + .expectNext(ByteBuffer.wrap("foo".getBytes()), ByteBuffer.wrap("bar".getBytes())) + .expectComplete() + .verify(output); } } diff --git a/spring-core/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java index 1839cd065d..51db6cd38c 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java @@ -24,11 +24,11 @@ import org.junit.Before; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertArrayEquals; @@ -67,17 +67,19 @@ public class ByteBufferEncoderTests extends AbstractDataBufferAllocatingTestCase Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClassWithGenerics(Publisher.class, ByteBuffer.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertValuesWith(b -> { + ScriptedSubscriber.create() + .consumeNextWith(b -> { byte[] buf = new byte[3]; b.read(buf); assertArrayEquals(fooBytes, buf); - }, b -> { + }) + .consumeNextWith(b -> { byte[] buf = new byte[3]; b.read(buf); assertArrayEquals(barBytes, buf); - }); + }) + .expectComplete() + .verify(output); } } diff --git a/spring-core/src/test/java/org/springframework/core/codec/CharSequenceEncoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/CharSequenceEncoderTests.java index 2575aa899d..ed294f1893 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/CharSequenceEncoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/CharSequenceEncoderTests.java @@ -23,11 +23,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertFalse; @@ -61,27 +61,25 @@ public class CharSequenceEncoderTests extends AbstractDataBufferAllocatingTestCa } @Test - public void writeString() throws InterruptedException { + public void writeString() { Flux stringFlux = Flux.just("foo"); Flux output = Flux.from( - this.encoder.encode(stringFlux, this.bufferFactory, null, null,Collections.emptyMap())); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer("foo")); + this.encoder.encode(stringFlux, this.bufferFactory, null, null, Collections.emptyMap())); + ScriptedSubscriber.create() + .consumeNextWith(stringConsumer("foo")) + .expectComplete() + .verify(output); } @Test - public void writeStringBuilder() throws InterruptedException { + public void writeStringBuilder() { Flux stringBuilderFlux = Flux.just(new StringBuilder("foo")); Flux output = Flux.from( this.encoder.encode(stringBuilderFlux, this.bufferFactory, null, null, Collections.emptyMap())); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer("foo")); + ScriptedSubscriber.create() + .consumeNextWith(stringConsumer("foo")) + .expectComplete() + .verify(output); } } diff --git a/spring-core/src/test/java/org/springframework/core/codec/ResourceDecoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ResourceDecoderTests.java index 722215560a..5a66d02bde 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ResourceDecoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ResourceDecoderTests.java @@ -21,6 +21,7 @@ import java.util.Collections; import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; @@ -28,7 +29,6 @@ import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import org.springframework.util.StreamUtils; @@ -64,21 +64,18 @@ public class ResourceDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux result = this.decoder .decode(source, ResolvableType.forClass(Resource.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(resource -> { + ScriptedSubscriber.create() + .consumeNextWith(resource -> { try { - byte[] bytes = - StreamUtils.copyToByteArray(resource.getInputStream()); + byte[] bytes = StreamUtils.copyToByteArray(resource.getInputStream()); assertEquals("foobar", new String(bytes)); } catch (IOException e) { fail(e.getMessage()); } - }); - + }) + .expectComplete() + .verify(result); } } \ No newline at end of file diff --git a/spring-core/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java index d26bb9bcc6..64d8cb0e67 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java @@ -22,6 +22,7 @@ import java.util.Collections; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; @@ -29,7 +30,6 @@ import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertTrue; @@ -62,14 +62,13 @@ public class ResourceEncoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClass(Resource.class), - null, Collections.emptyMap()); - - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer(s)); + null, Collections.emptyMap()); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer(s)) + .expectComplete() + .verify(output); } } \ No newline at end of file diff --git a/spring-core/src/test/java/org/springframework/core/codec/ResourceRegionEncoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/ResourceRegionEncoderTests.java index 83f1ef3c02..c60132465f 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/ResourceRegionEncoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/ResourceRegionEncoderTests.java @@ -16,9 +16,6 @@ package org.springframework.core.codec; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -26,6 +23,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; @@ -36,11 +34,14 @@ import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.core.io.support.ResourceRegion; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeType; import org.springframework.util.MimeTypeUtils; import org.springframework.util.StringUtils; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * Test cases for {@link ResourceRegionEncoder} class. * @@ -80,10 +81,10 @@ public class ResourceRegionEncoderTests extends AbstractDataBufferAllocatingTest ResolvableType.forClass(ResourceRegion.class), MimeTypeUtils.APPLICATION_OCTET_STREAM , Collections.emptyMap()); - TestSubscriber.subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer("Spring")); + ScriptedSubscriber.create() + .consumeNextWith(stringConsumer("Spring")) + .expectComplete() + .verify(result); } @Test @@ -110,36 +111,34 @@ public class ResourceRegionEncoderTests extends AbstractDataBufferAllocatingTest return previous; }); - TestSubscriber - .subscribe(reduced) - .assertNoError() - .assertComplete() - .assertValuesWith(dataBuffer -> { - String content = DataBufferTestUtils.dumpString(dataBuffer, StandardCharsets.UTF_8); - String[] ranges = StringUtils.tokenizeToStringArray(content, "\r\n", false, true); - - assertThat(ranges[0], is("--" + boundary)); - assertThat(ranges[1], is("Content-Type: text/plain")); - assertThat(ranges[2], is("Content-Range: bytes 0-5/39")); - assertThat(ranges[3], is("Spring")); - - assertThat(ranges[4], is("--" + boundary)); - assertThat(ranges[5], is("Content-Type: text/plain")); - assertThat(ranges[6], is("Content-Range: bytes 7-15/39")); - assertThat(ranges[7], is("Framework")); - - assertThat(ranges[8], is("--" + boundary)); - assertThat(ranges[9], is("Content-Type: text/plain")); - assertThat(ranges[10], is("Content-Range: bytes 17-20/39")); - assertThat(ranges[11], is("test")); - - assertThat(ranges[12], is("--" + boundary)); - assertThat(ranges[13], is("Content-Type: text/plain")); - assertThat(ranges[14], is("Content-Range: bytes 22-38/39")); - assertThat(ranges[15], is("resource content.")); - - assertThat(ranges[16], is("--" + boundary + "--")); - }); + ScriptedSubscriber.create() + .consumeNextWith(buf -> { + String content = DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8); + String[] ranges = StringUtils.tokenizeToStringArray(content, "\r\n", + false, true); + String[] expected = new String[] { + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 0-5/39", + "Spring", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 7-15/39", + "Framework", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 17-20/39", + "test", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 22-38/39", + "resource content.", + "--" + boundary + "--" + }; + assertArrayEquals(expected, ranges); + }) + .expectComplete() + .verify(reduced); } } diff --git a/spring-core/src/test/java/org/springframework/core/codec/StringDecoderTests.java b/spring-core/src/test/java/org/springframework/core/codec/StringDecoderTests.java index ff95273d32..ebb99e4d6b 100644 --- a/spring-core/src/test/java/org/springframework/core/codec/StringDecoderTests.java +++ b/spring-core/src/test/java/org/springframework/core/codec/StringDecoderTests.java @@ -21,11 +21,11 @@ import java.util.Collections; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.junit.Assert.assertFalse; @@ -61,11 +61,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux source = Flux.just(stringBuffer("foo"), stringBuffer("bar"), stringBuffer("baz")); Flux output = this.decoder.decode(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); + ScriptedSubscriber + .create() + .expectNext("foo", "bar", "baz") + .expectComplete().verify(output); - TestSubscriber.subscribe(output) - .assertNoError() - .assertComplete() - .assertValues("foo", "bar", "baz"); } @Test @@ -75,10 +75,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux source = Flux.just(fooBar, baz); Flux output = decoder.decode(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); + ScriptedSubscriber + .create() + .expectNext("\n", "foo\r", "\n", "bar\r", "\n", "baz") + .expectComplete().verify(output); - TestSubscriber.subscribe(output) - .assertNoError() - .assertComplete().assertValues("\n", "foo\r", "\n", "bar\r", "\n", "baz"); } @Test @@ -87,10 +88,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); - TestSubscriber.subscribe(output) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete().verify(output); + } @Test @@ -99,7 +101,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); - TestSubscriber.subscribe(output).assertValues(""); + ScriptedSubscriber + .create() + .expectNext("") + .expectComplete().verify(output); + } @Test @@ -109,10 +115,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Mono output = this.decoder.decodeToMono(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); - TestSubscriber.subscribe(output) - .assertNoError() - .assertComplete() - .assertValues("foobarbaz"); + ScriptedSubscriber + .create() + .expectNext("foobarbaz") + .expectComplete() + .verify(output); } @Test @@ -121,10 +128,11 @@ public class StringDecoderTests extends AbstractDataBufferAllocatingTestCase { Mono output = this.decoder.decodeToMono(source, ResolvableType.forClass(String.class), null, Collections.emptyMap()); - TestSubscriber.subscribe(output) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete() + .verify(output); } } diff --git a/spring-core/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java b/spring-core/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java index ed948ca3a6..272af8c01d 100644 --- a/spring-core/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java +++ b/spring-core/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java @@ -27,7 +27,7 @@ import org.junit.runners.Parameterized; import org.springframework.core.io.buffer.support.DataBufferTestUtils; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; /** * @author Arjen Poutsma @@ -40,7 +40,7 @@ public abstract class AbstractDataBufferAllocatingTestCase { @Parameterized.Parameters(name = "{0}") public static Object[][] dataBufferFactories() { - return new Object[][]{ + return new Object[][] { {new NettyDataBufferFactory(new UnpooledByteBufAllocator(true))}, {new NettyDataBufferFactory(new UnpooledByteBufAllocator(false))}, {new NettyDataBufferFactory(new PooledByteBufAllocator(true))}, diff --git a/spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferUtilsTests.java b/spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferUtilsTests.java index a132952f1d..757b2a83f5 100644 --- a/spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferUtilsTests.java @@ -24,9 +24,9 @@ import java.nio.file.StandardOpenOption; import org.junit.Test; import reactor.core.publisher.Flux; -import org.springframework.tests.TestSubscriber; +import reactor.test.subscriber.ScriptedSubscriber; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; /** * @author Arjen Poutsma @@ -39,13 +39,13 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase { FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ); Flux flux = DataBufferUtils.read(channel, this.bufferFactory, 3); - TestSubscriber - .subscribe(flux) - .assertNoError() - .assertComplete() - .assertValuesWith( - stringConsumer("foo"), stringConsumer("bar"), - stringConsumer("baz"), stringConsumer("qux")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("foo")) + .consumeNextWith(stringConsumer("bar")) + .consumeNextWith(stringConsumer("baz")) + .consumeNextWith(stringConsumer("qux")) + .expectComplete().verify(flux); assertFalse(channel.isOpen()); } @@ -56,77 +56,74 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase { FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ); Flux flux = DataBufferUtils.read(channel, this.bufferFactory, 5); - TestSubscriber - .subscribe(flux) - .assertNoError() - .assertComplete() - .assertValuesWith( - stringConsumer("fooba"), stringConsumer("rbazq"), - stringConsumer("ux") - ); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("fooba")) + .consumeNextWith(stringConsumer("rbazq")) + .consumeNextWith(stringConsumer("ux")) + .expectComplete().verify(flux); assertFalse(channel.isOpen()); } @Test - public void readInputStream() { + public void readInputStream() throws Exception { InputStream is = DataBufferUtilsTests.class.getResourceAsStream("DataBufferUtilsTests.txt"); Flux flux = DataBufferUtils.read(is, this.bufferFactory, 3); - TestSubscriber - .subscribe(flux) - .assertNoError() - .assertComplete() - .assertValuesWith( - stringConsumer("foo"), stringConsumer("bar"), - stringConsumer("baz"), stringConsumer("qux")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("foo")) + .consumeNextWith(stringConsumer("bar")) + .consumeNextWith(stringConsumer("baz")) + .consumeNextWith(stringConsumer("qux")) + .expectComplete().verify(flux); } @Test - public void takeUntilByteCount() { + public void takeUntilByteCount() throws Exception { DataBuffer foo = stringBuffer("foo"); DataBuffer bar = stringBuffer("bar"); DataBuffer baz = stringBuffer("baz"); Flux flux = Flux.just(foo, bar, baz); Flux result = DataBufferUtils.takeUntilByteCount(flux, 5L); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer("foo"), stringConsumer("ba")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("foo")) + .consumeNextWith(stringConsumer("ba")) + .expectComplete().verify(result); release(baz); } @Test - public void skipUntilByteCount() { + public void skipUntilByteCount() throws Exception { DataBuffer foo = stringBuffer("foo"); DataBuffer bar = stringBuffer("bar"); DataBuffer baz = stringBuffer("baz"); Flux flux = Flux.just(foo, bar, baz); Flux result = DataBufferUtils.skipUntilByteCount(flux, 5L); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(stringConsumer("r"), stringConsumer("baz")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("r")) + .consumeNextWith(stringConsumer("baz")) + .expectComplete().verify(result); } @Test - public void skipUntilByteCountShouldSkipAll() { + public void skipUntilByteCountShouldSkipAll() throws Exception { DataBuffer foo = stringBuffer("foo"); DataBuffer bar = stringBuffer("bar"); DataBuffer baz = stringBuffer("baz"); Flux flux = Flux.just(foo, bar, baz); Flux result = DataBufferUtils.skipUntilByteCount(flux, 9L); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertNoValues() - .assertComplete(); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete().verify(result); } } diff --git a/spring-core/src/test/java/org/springframework/tests/TestSubscriber.java b/spring-core/src/test/java/org/springframework/tests/TestSubscriber.java deleted file mode 100644 index 7d4a70380d..0000000000 --- a/spring-core/src/test/java/org/springframework/tests/TestSubscriber.java +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * Copyright (c) 2011-2016 Pivotal Software Inc, All Rights Reserved. - * - * 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.tests; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import reactor.core.Fuseable; -import reactor.core.Receiver; -import reactor.core.Trackable; -import reactor.core.publisher.Operators; - -/** - * A Reactor based Subscriber implementation that hosts assertion tests for its state and - * allows asynchronous cancellation and requesting. - * - *

To create a new instance of {@link TestSubscriber}, you have the choice between - * these static methods: - *

    - *
  • {@link TestSubscriber#subscribe(Publisher)}: create a new {@link TestSubscriber}, - * subscribe to it with the specified {@link Publisher} and requests an unbounded - * number of elements.
  • - *
  • {@link TestSubscriber#subscribe(Publisher, long)}: create a new {@link TestSubscriber}, - * subscribe to it with the specified {@link Publisher} and requests {@code n} elements - * (can be 0 if you want no initial demand). - *
  • {@link TestSubscriber#create()}: create a new {@link TestSubscriber} and requests - * an unbounded number of elements.
  • - *
  • {@link TestSubscriber#create(long)}: create a new {@link TestSubscriber} and - * requests {@code n} elements (can be 0 if you want no initial demand). - *
- * - *

If you are testing asynchronous publishers, don't forget to use one of the - * {@code await*()} methods to wait for the data to assert. - * - *

You can extend this class but only the onNext, onError and onComplete can be overridden. - * You can call {@link #request(long)} and {@link #cancel()} from any thread or from within - * the overridable methods but you should avoid calling the assertXXX methods asynchronously. - * - *

Usage: - *

- * {@code
- * TestSubscriber
- *   .subscribe(publisher)
- *   .await()
- *   .assertValues("ABC", "DEF");
- * }
- * 
- * - * @param the value type. - * - * @author Sebastien Deleuze - * @author David Karnok - * @author Anatoly Kadyshev - * @author Stephane Maldini - * @author Brian Clozel - */ -public class TestSubscriber - implements Subscriber, Subscription, Trackable, Receiver { - - /** - * Default timeout for waiting next values to be received - */ - public static final Duration DEFAULT_VALUES_TIMEOUT = Duration.ofSeconds(3); - - @SuppressWarnings("rawtypes") - private static final AtomicLongFieldUpdater REQUESTED = - AtomicLongFieldUpdater.newUpdater(TestSubscriber.class, "requested"); - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater NEXT_VALUES = - AtomicReferenceFieldUpdater.newUpdater(TestSubscriber.class, List.class, - "values"); - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater S = - AtomicReferenceFieldUpdater.newUpdater(TestSubscriber.class, Subscription.class, "s"); - - - private final List errors = new LinkedList<>(); - - private final CountDownLatch cdl = new CountDownLatch(1); - - volatile Subscription s; - - volatile long requested; - - volatile List values = new LinkedList<>(); - - /** - * The fusion mode to request. - */ - private int requestedFusionMode = -1; - - /** - * The established fusion mode. - */ - private volatile int establishedFusionMode = -1; - - /** - * The fuseable QueueSubscription in case a fusion mode was specified. - */ - private Fuseable.QueueSubscription qs; - - private int subscriptionCount = 0; - - private int completionCount = 0; - - private volatile long valueCount = 0L; - - private volatile long nextValueAssertedCount = 0L; - - private Duration valuesTimeout = DEFAULT_VALUES_TIMEOUT; - - private boolean valuesStorage = true; - -// ============================================================================================================== -// Static methods -// ============================================================================================================== - - /** - * Blocking method that waits until {@code conditionSupplier} returns true, or if it - * does not before the specified timeout, throws an {@link AssertionError} with the - * specified error message supplier. - * - * @param timeout the timeout duration - * @param errorMessageSupplier the error message supplier - * @param conditionSupplier condition to break out of the wait loop - * - * @throws AssertionError - */ - public static void await(Duration timeout, Supplier errorMessageSupplier, - BooleanSupplier conditionSupplier) { - - Objects.requireNonNull(errorMessageSupplier); - Objects.requireNonNull(conditionSupplier); - Objects.requireNonNull(timeout); - - long timeoutNs = timeout.toNanos(); - long startTime = System.nanoTime(); - do { - if (conditionSupplier.getAsBoolean()) { - return; - } - try { - Thread.sleep(100); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - while (System.nanoTime() - startTime < timeoutNs); - throw new AssertionError(errorMessageSupplier.get()); - } - - /** - * Blocking method that waits until {@code conditionSupplier} returns true, or if it - * does not before the specified timeout, throw an {@link AssertionError} with the - * specified error message. - * - * @param timeout the timeout duration - * @param errorMessage the error message - * @param conditionSupplier condition to break out of the wait loop - * - * @throws AssertionError - */ - public static void await(Duration timeout, - final String errorMessage, - BooleanSupplier conditionSupplier) { - await(timeout, new Supplier() { - @Override - public String get() { - return errorMessage; - } - }, conditionSupplier); - } - - /** - * Create a new {@link TestSubscriber} that requests an unbounded number of elements. - *

Be sure at least a publisher has subscribed to it via {@link Publisher#subscribe(Subscriber)} - * before use assert methods. - * @see #subscribe(Publisher) - * @param the observed value type - * @return a fresh TestSubscriber instance - */ - public static TestSubscriber create() { - return new TestSubscriber<>(); - } - - /** - * Create a new {@link TestSubscriber} that requests initially {@code n} elements. You - * can then manage the demand with {@link Subscription#request(long)}. - *

Be sure at least a publisher has subscribed to it via {@link Publisher#subscribe(Subscriber)} - * before use assert methods. - * @param n Number of elements to request (can be 0 if you want no initial demand). - * @see #subscribe(Publisher, long) - * @param the observed value type - * @return a fresh TestSubscriber instance - */ - public static TestSubscriber create(long n) { - return new TestSubscriber<>(n); - } - - /** - * Create a new {@link TestSubscriber} that requests an unbounded number of elements, - * and make the specified {@code publisher} subscribe to it. - * @param publisher The publisher to subscribe with - * @param the observed value type - * @return a fresh TestSubscriber instance - */ - public static TestSubscriber subscribe(Publisher publisher) { - TestSubscriber subscriber = new TestSubscriber<>(); - publisher.subscribe(subscriber); - return subscriber; - } - - /** - * Create a new {@link TestSubscriber} that requests initially {@code n} elements, - * and make the specified {@code publisher} subscribe to it. You can then manage the - * demand with {@link Subscription#request(long)}. - * @param publisher The publisher to subscribe with - * @param n Number of elements to request (can be 0 if you want no initial demand). - * @param the observed value type - * @return a fresh TestSubscriber instance - */ - public static TestSubscriber subscribe(Publisher publisher, long n) { - TestSubscriber subscriber = new TestSubscriber<>(n); - publisher.subscribe(subscriber); - return subscriber; - } - -// ============================================================================================================== -// Private constructors -// ============================================================================================================== - - private TestSubscriber() { - this(Long.MAX_VALUE); - } - - private TestSubscriber(long n) { - if (n < 0) { - throw new IllegalArgumentException("initialRequest >= required but it was " + n); - } - REQUESTED.lazySet(this, n); - } - -// ============================================================================================================== -// Configuration -// ============================================================================================================== - - - /** - * Enable or disabled the values storage. It is enabled by default, and can be disable - * in order to be able to perform performance benchmarks or tests with a huge amount - * values. - * @param enabled enable value storage? - * @return this - */ - public final TestSubscriber configureValuesStorage(boolean enabled) { - this.valuesStorage = enabled; - return this; - } - - /** - * Configure the timeout in seconds for waiting next values to be received (3 seconds - * by default). - * @param timeout the new default value timeout duration - * @return this - */ - public final TestSubscriber configureValuesTimeout(Duration timeout) { - this.valuesTimeout = timeout; - return this; - } - - /** - * Returns the established fusion mode or -1 if it was not enabled - * - * @return the fusion mode, see Fuseable constants - */ - public final int establishedFusionMode() { - return establishedFusionMode; - } - -// ============================================================================================================== -// Assertions -// ============================================================================================================== - - /** - * Assert a complete successfully signal has been received. - * @return this - */ - public final TestSubscriber assertComplete() { - assertNoError(); - int c = completionCount; - if (c == 0) { - throw new AssertionError("Not completed", null); - } - if (c > 1) { - throw new AssertionError("Multiple completions: " + c, null); - } - return this; - } - - /** - * Assert the specified values have been received. Values storage should be enabled to - * use this method. - * @param expectedValues the values to assert - * @see #configureValuesStorage(boolean) - * @return this - */ - public final TestSubscriber assertContainValues(Set expectedValues) { - if (!valuesStorage) { - throw new IllegalStateException( - "Using assertNoValues() requires enabling values storage"); - } - if (expectedValues.size() > values.size()) { - throw new AssertionError("Actual contains fewer elements" + values, null); - } - - Iterator expected = expectedValues.iterator(); - - for (; ; ) { - boolean n2 = expected.hasNext(); - if (n2) { - T t2 = expected.next(); - if (!values.contains(t2)) { - throw new AssertionError("The element is not contained in the " + - "received resuls" + - " = " + valueAndClass(t2), null); - } - } - else{ - break; - } - } - return this; - } - - /** - * Assert an error signal has been received. - * @return this - */ - public final TestSubscriber assertError() { - assertNotComplete(); - int s = errors.size(); - if (s == 0) { - throw new AssertionError("No error", null); - } - if (s > 1) { - throw new AssertionError("Multiple errors: " + s, null); - } - return this; - } - - /** - * Assert an error signal has been received. - * @param clazz The class of the exception contained in the error signal - * @return this - */ - public final TestSubscriber assertError(Class clazz) { - assertNotComplete(); - int s = errors.size(); - if (s == 0) { - throw new AssertionError("No error", null); - } - if (s == 1) { - Throwable e = errors.get(0); - if (!clazz.isInstance(e)) { - throw new AssertionError("Error class incompatible: expected = " + - clazz + ", actual = " + e, null); - } - } - if (s > 1) { - throw new AssertionError("Multiple errors: " + s, null); - } - return this; - } - - public final TestSubscriber assertErrorMessage(String message) { - assertNotComplete(); - int s = errors.size(); - if (s == 0) { - assertionError("No error", null); - } - if (s == 1) { - if (!Objects.equals(message, - errors.get(0) - .getMessage())) { - assertionError("Error class incompatible: expected = \"" + message + - "\", actual = \"" + errors.get(0).getMessage() + "\"", null); - } - } - if (s > 1) { - assertionError("Multiple errors: " + s, null); - } - - return this; - } - - /** - * Assert an error signal has been received. - * @param expectation A method that can verify the exception contained in the error signal - * and throw an exception (like an {@link AssertionError}) if the exception is not valid. - * @return this - */ - public final TestSubscriber assertErrorWith(Consumer expectation) { - assertNotComplete(); - int s = errors.size(); - if (s == 0) { - throw new AssertionError("No error", null); - } - if (s == 1) { - expectation.accept(errors.get(0)); - } - if (s > 1) { - throw new AssertionError("Multiple errors: " + s, null); - } - return this; - } - - /** - * Assert that the upstream was a Fuseable source. - * - * @return this - */ - public final TestSubscriber assertFuseableSource() { - if (qs == null) { - throw new AssertionError("Upstream was not Fuseable"); - } - return this; - } - - /** - * Assert that the fusion mode was granted. - * - * @return this - */ - public final TestSubscriber assertFusionEnabled() { - if (establishedFusionMode != Fuseable.SYNC && establishedFusionMode != Fuseable.ASYNC) { - throw new AssertionError("Fusion was not enabled"); - } - return this; - } - - public final TestSubscriber assertFusionMode(int expectedMode) { - if (establishedFusionMode != expectedMode) { - throw new AssertionError("Wrong fusion mode: expected: " + fusionModeName( - expectedMode) + ", actual: " + fusionModeName(establishedFusionMode)); - } - return this; - } - - /** - * Assert that the fusion mode was granted. - * - * @return this - */ - public final TestSubscriber assertFusionRejected() { - if (establishedFusionMode != Fuseable.NONE) { - throw new AssertionError("Fusion was granted"); - } - return this; - } - - /** - * Assert no error signal has been received. - * @return this - */ - public final TestSubscriber assertNoError() { - int s = errors.size(); - if (s == 1) { - Throwable e = errors.get(0); - String valueAndClass = e == null ? null : e + " (" + e.getClass().getSimpleName() + ")"; - throw new AssertionError("Error present: " + valueAndClass, null); - } - if (s > 1) { - throw new AssertionError("Multiple errors: " + s, null); - } - return this; - } - - /** - * Assert no values have been received. - * - * @return this - */ - public final TestSubscriber assertNoValues() { - if (valueCount != 0) { - throw new AssertionError("No values expected but received: [length = " + values.size() + "] " + values, - null); - } - return this; - } - - /** - * Assert that the upstream was not a Fuseable source. - * @return this - */ - public final TestSubscriber assertNonFuseableSource() { - if (qs != null) { - throw new AssertionError("Upstream was Fuseable"); - } - return this; - } - - /** - * Assert no complete successfully signal has been received. - * @return this - */ - public final TestSubscriber assertNotComplete() { - int c = completionCount; - if (c == 1) { - throw new AssertionError("Completed", null); - } - if (c > 1) { - throw new AssertionError("Multiple completions: " + c, null); - } - return this; - } - - /** - * Assert no subscription occurred. - * - * @return this - */ - public final TestSubscriber assertNotSubscribed() { - int s = subscriptionCount; - - if (s == 1) { - throw new AssertionError("OnSubscribe called once", null); - } - if (s > 1) { - throw new AssertionError("OnSubscribe called multiple times: " + s, null); - } - - return this; - } - - /** - * Assert no complete successfully or error signal has been received. - * @return this - */ - public final TestSubscriber assertNotTerminated() { - if (cdl.getCount() == 0) { - throw new AssertionError("Terminated", null); - } - return this; - } - - /** - * Assert subscription occurred (once). - * @return this - */ - public final TestSubscriber assertSubscribed() { - int s = subscriptionCount; - - if (s == 0) { - throw new AssertionError("OnSubscribe not called", null); - } - if (s > 1) { - throw new AssertionError("OnSubscribe called multiple times: " + s, null); - } - - return this; - } - - /** - * Assert either complete successfully or error signal has been received. - * @return this - */ - public final TestSubscriber assertTerminated() { - if (cdl.getCount() != 0) { - throw new AssertionError("Not terminated", null); - } - return this; - } - - /** - * Assert {@code n} values has been received. - * - * @param n the expected value count - * - * @return this - */ - public final TestSubscriber assertValueCount(long n) { - if (valueCount != n) { - throw new AssertionError("Different value count: expected = " + n + ", actual = " + valueCount, - null); - } - return this; - } - - /** - * Assert the specified values have been received in the same order read by the - * passed {@link Iterable}. Values storage - * should be enabled to - * use this method. - * @param expectedSequence the values to assert - * @see #configureValuesStorage(boolean) - * @return this - */ - public final TestSubscriber assertValueSequence(Iterable expectedSequence) { - if (!valuesStorage) { - throw new IllegalStateException("Using assertNoValues() requires enabling values storage"); - } - Iterator actual = values.iterator(); - Iterator expected = expectedSequence.iterator(); - int i = 0; - for (; ; ) { - boolean n1 = actual.hasNext(); - boolean n2 = expected.hasNext(); - if (n1 && n2) { - T t1 = actual.next(); - T t2 = expected.next(); - if (!Objects.equals(t1, t2)) { - throw new AssertionError("The element with index " + i + " does not match: expected = " + valueAndClass(t2) + ", actual = " - + valueAndClass( - t1), null); - } - i++; - } else if (n1 && !n2) { - throw new AssertionError("Actual contains more elements" + values, null); - } else if (!n1 && n2) { - throw new AssertionError("Actual contains fewer elements: " + values, null); - } else { - break; - } - } - return this; - } - - /** - * Assert the specified values have been received in the declared order. Values - * storage should be enabled to use this method. - * - * @param expectedValues the values to assert - * - * @return this - * - * @see #configureValuesStorage(boolean) - */ - @SafeVarargs - public final TestSubscriber assertValues(T... expectedValues) { - return assertValueSequence(Arrays.asList(expectedValues)); - } - - /** - * Assert the specified values have been received in the declared order. Values - * storage should be enabled to use this method. - * - * @param expectations One or more methods that can verify the values and throw a - * exception (like an {@link AssertionError}) if the value is not valid. - * - * @return this - * - * @see #configureValuesStorage(boolean) - */ - @SafeVarargs - public final TestSubscriber assertValuesWith(Consumer... expectations) { - if (!valuesStorage) { - throw new IllegalStateException( - "Using assertNoValues() requires enabling values storage"); - } - final int expectedValueCount = expectations.length; - if (expectedValueCount != values.size()) { - throw new AssertionError("Different value count: expected = " + expectedValueCount + ", actual = " + valueCount, null); - } - for (int i = 0; i < expectedValueCount; i++) { - Consumer consumer = expectations[i]; - T actualValue = values.get(i); - consumer.accept(actualValue); - } - return this; - } - -// ============================================================================================================== -// Await methods -// ============================================================================================================== - - /** - * Blocking method that waits until a complete successfully or error signal is received. - * @return this - */ - public final TestSubscriber await() { - if (cdl.getCount() == 0) { - return this; - } - try { - cdl.await(); - } catch (InterruptedException ex) { - throw new AssertionError("Wait interrupted", ex); - } - return this; - } - - /** - * Blocking method that waits until a complete successfully or error signal is received - * or until a timeout occurs. - * @param timeout The timeout value - * @return this - */ - public final TestSubscriber await(Duration timeout) { - if (cdl.getCount() == 0) { - return this; - } - try { - if (!cdl.await(timeout.toMillis(), TimeUnit.MILLISECONDS)) { - throw new AssertionError("No complete or error signal before timeout"); - } - return this; - } - catch (InterruptedException ex) { - throw new AssertionError("Wait interrupted", ex); - } - } - - /** - * Blocking method that waits until {@code n} next values have been received. - * - * @param n the value count to assert - * - * @return this - */ - public final TestSubscriber awaitAndAssertNextValueCount(final long n) { - await(valuesTimeout, () -> { - if(valuesStorage){ - return String.format("%d out of %d next values received within %d, " + - "values : %s", - valueCount - nextValueAssertedCount, - n, - valuesTimeout.toMillis(), - values.toString() - ); - } - return String.format("%d out of %d next values received within %d", - valueCount - nextValueAssertedCount, - n, - valuesTimeout.toMillis()); - }, () -> valueCount >= (nextValueAssertedCount + n)); - nextValueAssertedCount += n; - return this; - } - - /** - * Blocking method that waits until {@code n} next values have been received (n is the - * number of values provided) to assert them. - * - * @param values the values to assert - * - * @return this - */ - @SafeVarargs - @SuppressWarnings("unchecked") - public final TestSubscriber awaitAndAssertNextValues(T... values) { - final int expectedNum = values.length; - final List> expectations = new ArrayList<>(); - for (int i = 0; i < expectedNum; i++) { - final T expectedValue = values[i]; - expectations.add(actualValue -> { - if (!actualValue.equals(expectedValue)) { - throw new AssertionError(String.format( - "Expected Next signal: %s, but got: %s", - expectedValue, - actualValue)); - } - }); - } - awaitAndAssertNextValuesWith(expectations.toArray((Consumer[]) new Consumer[0])); - return this; - } - - /** - * Blocking method that waits until {@code n} next values have been received - * (n is the number of expectations provided) to assert them. - * @param expectations One or more methods that can verify the values and throw a - * exception (like an {@link AssertionError}) if the value is not valid. - * @return this - */ - @SafeVarargs - public final TestSubscriber awaitAndAssertNextValuesWith(Consumer... expectations) { - valuesStorage = true; - final int expectedValueCount = expectations.length; - await(valuesTimeout, () -> { - if(valuesStorage){ - return String.format("%d out of %d next values received within %d, " + - "values : %s", - valueCount - nextValueAssertedCount, - expectedValueCount, - valuesTimeout.toMillis(), - values.toString() - ); - } - return String.format("%d out of %d next values received within %d ms", - valueCount - nextValueAssertedCount, - expectedValueCount, - valuesTimeout.toMillis()); - }, () -> valueCount >= (nextValueAssertedCount + expectedValueCount)); - List nextValuesSnapshot; - List empty = new ArrayList<>(); - for(;;){ - nextValuesSnapshot = values; - if(NEXT_VALUES.compareAndSet(this, values, empty)){ - break; - } - } - if (nextValuesSnapshot.size() < expectedValueCount) { - throw new AssertionError(String.format("Expected %d number of signals but received %d", - expectedValueCount, - nextValuesSnapshot.size())); - } - for (int i = 0; i < expectedValueCount; i++) { - Consumer consumer = expectations[i]; - T actualValue = nextValuesSnapshot.get(i); - consumer.accept(actualValue); - } - nextValueAssertedCount += expectedValueCount; - return this; - } - -// ============================================================================================================== -// Overrides -// ============================================================================================================== - - @Override - public void cancel() { - Subscription a = s; - if (a != Operators.cancelledSubscription()) { - a = S.getAndSet(this, Operators.cancelledSubscription()); - if (a != null && a != Operators.cancelledSubscription()) { - a.cancel(); - } - } - } - - @Override - public final boolean isCancelled() { - return s == Operators.cancelledSubscription(); - } - - @Override - public final boolean isStarted() { - return s != null; - } - - @Override - public final boolean isTerminated() { - return isCancelled(); - } - - @Override - public void onComplete() { - completionCount++; - cdl.countDown(); - } - - @Override - public void onError(Throwable t) { - errors.add(t); - cdl.countDown(); - } - - @Override - public void onNext(T t) { - if (establishedFusionMode == Fuseable.ASYNC) { - for (; ; ) { - t = qs.poll(); - if (t == null) { - break; - } - valueCount++; - if (valuesStorage) { - List nextValuesSnapshot; - for (; ; ) { - nextValuesSnapshot = values; - nextValuesSnapshot.add(t); - if (NEXT_VALUES.compareAndSet(this, - nextValuesSnapshot, - nextValuesSnapshot)) { - break; - } - } - } - } - } - else { - valueCount++; - if (valuesStorage) { - List nextValuesSnapshot; - for (; ; ) { - nextValuesSnapshot = values; - nextValuesSnapshot.add(t); - if (NEXT_VALUES.compareAndSet(this, - nextValuesSnapshot, - nextValuesSnapshot)) { - break; - } - } - } - } - } - - @Override - @SuppressWarnings("unchecked") - public void onSubscribe(Subscription s) { - subscriptionCount++; - int requestMode = requestedFusionMode; - if (requestMode >= 0) { - if (!setWithoutRequesting(s)) { - if (!isCancelled()) { - errors.add(new IllegalStateException("Subscription already set: " + - subscriptionCount)); - } - } else { - if (s instanceof Fuseable.QueueSubscription) { - this.qs = (Fuseable.QueueSubscription)s; - - int m = qs.requestFusion(requestMode); - establishedFusionMode = m; - - if (m == Fuseable.SYNC) { - for (;;) { - T v = qs.poll(); - if (v == null) { - onComplete(); - break; - } - - onNext(v); - } - } - else { - requestDeferred(); - } - } - else { - requestDeferred(); - } - } - } else { - if (!set(s)) { - if (!isCancelled()) { - errors.add(new IllegalStateException("Subscription already set: " + - subscriptionCount)); - } - } - } - } - - @Override - public void request(long n) { - if (Operators.validate(n)) { - if (establishedFusionMode != Fuseable.SYNC) { - normalRequest(n); - } - } - } - - @Override - public final long requestedFromDownstream() { - return requested; - } - - /** - * Setup what fusion mode should be requested from the incomining - * Subscription if it happens to be QueueSubscription - * @param requestMode the mode to request, see Fuseable constants - * @return this - */ - public final TestSubscriber requestedFusionMode(int requestMode) { - this.requestedFusionMode = requestMode; - return this; - } - - @Override - public Subscription upstream() { - return s; - } - - -// ============================================================================================================== -// Non public methods -// ============================================================================================================== - - protected final void normalRequest(long n) { - Subscription a = s; - if (a != null) { - a.request(n); - } else { - Operators.addAndGet(REQUESTED, this, n); - - a = s; - - if (a != null) { - long r = REQUESTED.getAndSet(this, 0L); - - if (r != 0L) { - a.request(r); - } - } - } - } - - /** - * Requests the deferred amount if not zero. - */ - protected final void requestDeferred() { - long r = REQUESTED.getAndSet(this, 0L); - - if (r != 0L) { - s.request(r); - } - } - - /** - * Atomically sets the single subscription and requests the missed amount from it. - * - * @param s - * @return false if this arbiter is cancelled or there was a subscription already set - */ - protected final boolean set(Subscription s) { - Objects.requireNonNull(s, "s"); - Subscription a = this.s; - if (a == Operators.cancelledSubscription()) { - s.cancel(); - return false; - } - if (a != null) { - s.cancel(); - Operators.reportSubscriptionSet(); - return false; - } - - if (S.compareAndSet(this, null, s)) { - - long r = REQUESTED.getAndSet(this, 0L); - - if (r != 0L) { - s.request(r); - } - - return true; - } - - a = this.s; - - if (a != Operators.cancelledSubscription()) { - s.cancel(); - return false; - } - - Operators.reportSubscriptionSet(); - return false; - } - - /** - * Sets the Subscription once but does not request anything. - * @param s the Subscription to set - * @return true if successful, false if the current subscription is not null - */ - protected final boolean setWithoutRequesting(Subscription s) { - Objects.requireNonNull(s, "s"); - for (;;) { - Subscription a = this.s; - if (a == Operators.cancelledSubscription()) { - s.cancel(); - return false; - } - if (a != null) { - s.cancel(); - Operators.reportSubscriptionSet(); - return false; - } - - if (S.compareAndSet(this, null, s)) { - return true; - } - } - } - - /** - * Prepares and throws an AssertionError exception based on the message, cause, the - * active state and the potential errors so far. - * - * @param message the message - * @param cause the optional Throwable cause - * - * @throws AssertionError as expected - */ - protected final void assertionError(String message, Throwable cause) { - StringBuilder b = new StringBuilder(); - - if (cdl.getCount() != 0) { - b.append("(active) "); - } - b.append(message); - - List err = errors; - if (!err.isEmpty()) { - b.append(" (+ ") - .append(err.size()) - .append(" errors)"); - } - AssertionError e = new AssertionError(b.toString(), cause); - - for (Throwable t : err) { - e.addSuppressed(t); - } - - throw e; - } - - protected final String fusionModeName(int mode) { - switch (mode) { - case -1: - return "Disabled"; - case Fuseable.NONE: - return "None"; - case Fuseable.SYNC: - return "Sync"; - case Fuseable.ASYNC: - return "Async"; - default: - return "Unknown(" + mode + ")"; - } - } - - protected final String valueAndClass(Object o) { - if (o == null) { - return null; - } - return o + " (" + o.getClass().getSimpleName() + ")"; - } - -} diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java index bb8b719945..5d0ed18c26 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java @@ -23,6 +23,7 @@ import org.junit.Before; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -34,7 +35,6 @@ import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.stereotype.Controller; -import org.springframework.tests.TestSubscriber; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -52,7 +52,9 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.handler.ExceptionHandlingWebHandler; import org.springframework.web.server.session.MockWebSessionManager; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; @@ -97,9 +99,13 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/does-not-exist"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertError(ResponseStatusException.class) - .assertErrorMessage("Request failure [status: 404, reason: \"No matching handler\"]"); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertThat(error, instanceOf(ResponseStatusException.class)); + assertThat(error.getMessage(), + is("Request failure [status: 404, reason: \"No matching handler\"]")); + }) + .verify(publisher); } @Test @@ -107,9 +113,12 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/unknown-argument-type"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertError(IllegalStateException.class) - .assertErrorWith(ex -> assertThat(ex.getMessage(), startsWith("No resolver for argument [0]"))); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertThat(error, instanceOf(IllegalStateException.class)); + assertThat(error.getMessage(), startsWith("No resolver for argument [0]")); + }) + .verify(publisher); } @Test @@ -117,8 +126,11 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/error-signal"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertErrorWith(ex -> assertSame(EXCEPTION, ex)); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertSame(EXCEPTION, error); + }) + .verify(publisher); } @Test @@ -126,8 +138,11 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/raise-exception"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertErrorWith(ex -> assertSame(EXCEPTION, ex)); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertSame(EXCEPTION, error); + }) + .verify(publisher); } @Test @@ -135,9 +150,12 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/unknown-return-type"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertError(IllegalStateException.class) - .assertErrorWith(ex -> assertThat(ex.getMessage(), startsWith("No HandlerResultHandler"))); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertThat(error, instanceOf(IllegalStateException.class)); + assertThat(error.getMessage(), startsWith("No HandlerResultHandler")); + }) + .verify(publisher); } @Test @@ -145,8 +163,11 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/request-body").setHeader("Accept", "application/json").setBody("body"); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertError(NotAcceptableStatusException.class); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertThat(error, instanceOf(NotAcceptableStatusException.class)); + }) + .verify(publisher); } @Test @@ -154,9 +175,12 @@ public class DispatcherHandlerErrorTests { this.request.setUri("/request-body").setBody(Mono.error(EXCEPTION)); Mono publisher = this.dispatcherHandler.handle(this.exchange); - TestSubscriber.subscribe(publisher) - .assertError(ServerWebInputException.class) - .assertErrorWith(ex -> assertSame(EXCEPTION, ex.getCause())); + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertThat(error, instanceOf(ServerWebInputException.class)); + assertSame(EXCEPTION, error.getCause()); + }) + .verify(publisher); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/ResourceHandlerRegistryTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/ResourceHandlerRegistryTests.java index fed09be2e7..e4989dcfbc 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/ResourceHandlerRegistryTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/ResourceHandlerRegistryTests.java @@ -24,15 +24,16 @@ import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.CacheControl; import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.reactive.resource.AppCacheManifestTransformer; @@ -99,9 +100,11 @@ public class ResourceHandlerRegistryTests { ResourceWebHandler handler = getHandler("/resources/**"); handler.handle(this.exchange).blockMillis(5000); - TestSubscriber.subscribe(this.response.getBody()) - .assertValuesWith(buf -> assertEquals("test stylesheet content", - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> assertEquals("test stylesheet content", + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))) + .expectComplete() + .verify(this.response.getBody()); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java index 22d5096ec8..3d957ba657 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/SseHandlerFunctionIntegrationTests.java @@ -23,12 +23,12 @@ import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.BodyExtractors; import org.springframework.http.codec.ServerSentEvent; -import org.springframework.tests.TestSubscriber; import org.springframework.web.client.reactive.ClientRequest; import org.springframework.web.client.reactive.WebClient; @@ -74,10 +74,11 @@ public class SseHandlerFunctionIntegrationTests .map(s -> (s.replace("\n", ""))) .take(2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues("data:foo 0", "data:foo 1"); + ScriptedSubscriber.create() + .expectNext("data:foo 0") + .expectNext("data:foo 1") + .expectComplete() + .verify(result, Duration.ofSeconds(5)); } @Test @@ -96,10 +97,10 @@ public class SseHandlerFunctionIntegrationTests .takeUntil(s -> s.endsWith("foo 1\"}")) .reduce((s1, s2) -> s1 + s2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues("data:{\"name\":\"foo 0\"}data:{\"name\":\"foo 1\"}"); + ScriptedSubscriber.create() + .expectNext("data:{\"name\":\"foo 0\"}data:{\"name\":\"foo 1\"}") + .expectComplete() + .verify(result, Duration.ofSeconds(5)); } @Test @@ -117,14 +118,11 @@ public class SseHandlerFunctionIntegrationTests .map(s -> s.replace("\n", "")) .take(2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues( - "id:0:bardata:foo", - "id:1:bardata:foo" - ); - ; + ScriptedSubscriber.create() + .expectNext("id:0:bardata:foo") + .expectNext("id:1:bardata:foo") + .expectComplete() + .verify(result, Duration.ofSeconds(5)); } private static class SseHandler { diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java index a2d068bd8e..d70f742aea 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java @@ -16,10 +16,6 @@ package org.springframework.web.reactive.resource; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.springframework.web.reactive.HandlerMapping.*; - import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -32,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -48,17 +45,22 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.StringUtils; import org.springframework.web.reactive.accept.CompositeContentTypeResolver; import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; import org.springframework.web.server.MethodNotAllowedException; -import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.DefaultWebSessionManager; import org.springframework.web.server.session.WebSessionManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.springframework.web.reactive.HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE; + /** * Unit tests for {@link ResourceWebHandler}. * @@ -525,7 +527,10 @@ public class ResourceWebHandlerTests { this.request.addHeader("Range", "bytes= foo bar"); this.exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); - TestSubscriber.subscribe(this.handler.handle(this.exchange)).assertComplete(); + ScriptedSubscriber.create() + .expectNextCount(0) + .expectComplete() + .verify(this.handler.handle(this.exchange)); assertEquals(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE, this.response.getStatusCode()); assertEquals("bytes", this.response.getHeaders().getFirst("Accept-Ranges")); @@ -550,8 +555,8 @@ public class ResourceWebHandlerTests { return previous; }); - TestSubscriber.subscribe(reduced) - .assertValuesWith(buf -> { + ScriptedSubscriber.create() + .consumeNextWith(buf -> { String content = DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8); String[] ranges = StringUtils.tokenizeToStringArray(content, "\r\n", false, true); @@ -569,7 +574,9 @@ public class ResourceWebHandlerTests { assertEquals("Content-Type: text/plain", ranges[9]); assertEquals("Content-Range: bytes 8-9/10", ranges[10]); assertEquals("t.", ranges[11]); - }); + }) + .expectComplete() + .verify(reduced); } @Test // SPR-14005 @@ -591,9 +598,11 @@ public class ResourceWebHandlerTests { } private void assertResponseBody(String responseBody) { - TestSubscriber.subscribe(this.response.getBody()) - .assertValuesWith(buf -> assertEquals(responseBody, - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> assertEquals(responseBody, + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))) + .expectComplete() + .verify(this.response.getBody()); } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java index dc6d204366..47d198834f 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java @@ -26,13 +26,13 @@ import java.util.Set; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Controller; -import org.springframework.tests.TestSubscriber; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.bind.annotation.RequestMapping; @@ -100,7 +100,7 @@ public class HandlerMethodMappingTests { this.mapping.registerMapping("/fo?", this.handler, this.method2); Mono result = this.mapping.getHandler(createExchange(HttpMethod.GET, "/foo")); - TestSubscriber.subscribe(result).assertError(IllegalStateException.class); + ScriptedSubscriber.create().expectError(IllegalStateException.class).verify(result); } @Test @@ -193,11 +193,13 @@ public class HandlerMethodMappingTests { @Controller private static class MyHandler { - @RequestMapping @SuppressWarnings("unused") + @RequestMapping + @SuppressWarnings("unused") public void handlerMethod1() { } - @RequestMapping @SuppressWarnings("unused") + @RequestMapping + @SuppressWarnings("unused") public void handlerMethod2() { } } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java index 7b1e2ee3c5..d554707027 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/InvocableHandlerMethodTests.java @@ -21,11 +21,11 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.result.ResolvableMethod; import org.springframework.web.server.ServerWebExchange; @@ -33,7 +33,10 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.MockWebSessionManager; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -89,10 +92,13 @@ public class InvocableHandlerMethodTests { InvocableHandlerMethod hm = handlerMethod("singleArg"); Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); - TestSubscriber.subscribe(mono) - .assertError(IllegalStateException.class) - .assertErrorMessage("No resolver for argument [0] of type [java.lang.String] " + - "on method [" + hm.getMethod().toGenericString() + "]"); + ScriptedSubscriber.create().expectNextCount(0) + .consumeErrorWith(error -> { + assertThat(error, instanceOf(IllegalStateException.class)); + assertThat(error.getMessage(), is("No resolver for argument [0] of type [java.lang.String] " + + "on method [" + hm.getMethod().toGenericString() + "]")); + }) + .verify(mono); } @Test @@ -101,9 +107,12 @@ public class InvocableHandlerMethodTests { addResolver(hm, Mono.error(new UnsupportedMediaTypeStatusException("boo"))); Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); - TestSubscriber.subscribe(mono) - .assertError(UnsupportedMediaTypeStatusException.class) - .assertErrorMessage("Request failure [status: 415, reason: \"boo\"]"); + ScriptedSubscriber.create().expectNextCount(0) + .consumeErrorWith(error -> { + assertThat(error, instanceOf(UnsupportedMediaTypeStatusException.class)); + assertThat(error.getMessage(), is("Request failure [status: 415, reason: \"boo\"]")); + }) + .verify(mono); } @Test @@ -112,11 +121,14 @@ public class InvocableHandlerMethodTests { addResolver(hm, Mono.just(1)); Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); - TestSubscriber.subscribe(mono) - .assertError(IllegalStateException.class) - .assertErrorMessage("Failed to invoke controller with resolved arguments: " + - "[0][type=java.lang.Integer][value=1] " + - "on method [" + hm.getMethod().toGenericString() + "]"); + ScriptedSubscriber.create().expectNextCount(0) + .consumeErrorWith(error -> { + assertThat(error, instanceOf(IllegalStateException.class)); + assertThat(error.getMessage(), is("Failed to invoke controller with resolved arguments: " + + "[0][type=java.lang.Integer][value=1] " + + "on method [" + hm.getMethod().toGenericString() + "]")); + }) + .verify(mono); } @Test @@ -124,9 +136,12 @@ public class InvocableHandlerMethodTests { InvocableHandlerMethod hm = handlerMethod("exceptionMethod"); Mono mono = hm.invokeForRequest(this.exchange, new BindingContext()); - TestSubscriber.subscribe(mono) - .assertError(IllegalStateException.class) - .assertErrorMessage("boo"); + ScriptedSubscriber.create().expectNextCount(0) + .consumeErrorWith(error -> { + assertThat(error, instanceOf(IllegalStateException.class)); + assertThat(error.getMessage(), is("boo")); + }) + .verify(mono); } @@ -143,11 +158,14 @@ public class InvocableHandlerMethodTests { } private void assertHandlerResultValue(Mono mono, String expected) { - TestSubscriber.subscribe(mono).assertValuesWith(result -> { - Optional optional = result.getReturnValue(); - assertTrue(optional.isPresent()); - assertEquals(expected, optional.get()); - }); + ScriptedSubscriber.create() + .consumeNextWith(result -> { + Optional optional = result.getReturnValue(); + assertTrue(optional.isPresent()); + assertEquals(expected, optional.get()); + }) + .expectComplete() + .verify(mono); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java index 55f244e3d5..b0d464b4db 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java @@ -29,6 +29,7 @@ import java.util.function.Consumer; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationUtils; @@ -39,7 +40,6 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.stereotype.Controller; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -164,7 +164,9 @@ public class RequestMappingInfoHandlerMappingTests { this.handlerMapping.registerHandler(new UserController()); Mono mono = this.handlerMapping.getHandler(exchange); - TestSubscriber.subscribe(mono).assertError(NotAcceptableStatusException.class); + ScriptedSubscriber.create() + .expectError(NotAcceptableStatusException.class) + .verify(mono); } @Test // SPR-8462 @@ -350,12 +352,14 @@ public class RequestMappingInfoHandlerMappingTests { @SuppressWarnings("unchecked") private void assertError(Mono mono, final Class exceptionClass, final Consumer consumer) { - TestSubscriber - .subscribe(mono) - .assertErrorWith(ex -> { - assertEquals(exceptionClass, ex.getClass()); - consumer.accept((T) ex); - }); + + ScriptedSubscriber.create() + .consumeErrorWith(error -> { + assertEquals(exceptionClass, error.getClass()); + consumer.accept((T) error); + + }) + .verify(mono); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java index b19292b099..2dea44d203 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CookieValueMethodArgumentResolverTests.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.MethodParameter; @@ -30,7 +31,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; @@ -119,9 +119,10 @@ public class CookieValueMethodArgumentResolverTests { @Test public void notFound() { Mono mono = resolver.resolveArgument(this.cookieParameter, this.bindingContext, this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create() + .expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(mono); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java index 8b067ce37a..c9fe985ec7 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/HttpEntityArgumentResolverTests.java @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import rx.Observable; import rx.RxReactiveStreams; import rx.Single; @@ -44,7 +45,6 @@ import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.reactive.result.ResolvableMethod; import org.springframework.web.reactive.result.method.BindingContext; import org.springframework.web.server.ServerWebExchange; @@ -128,10 +128,7 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(Mono.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(entity.getBody()) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber.create().expectNextCount(0).expectComplete().verify(entity.getBody()); } @Test @@ -139,10 +136,7 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(Flux.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(entity.getBody()) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber.create().expectNextCount(0).expectComplete().verify(entity.getBody()); } @Test @@ -150,9 +144,10 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(Single.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(entity.getBody())) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber + .create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(RxReactiveStreams.toPublisher(entity.getBody())); } @Test @@ -160,9 +155,10 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(io.reactivex.Single.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(entity.getBody().toFlowable()) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber + .create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(entity.getBody().toFlowable()); } @Test @@ -170,10 +166,10 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(Observable.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(entity.getBody())) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create().expectNextCount(0) + .expectComplete() + .verify(RxReactiveStreams.toPublisher(entity.getBody())); } @Test @@ -181,10 +177,10 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(io.reactivex.Observable.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(entity.getBody().toFlowable(BackpressureStrategy.BUFFER)) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create().expectNextCount(0) + .expectComplete() + .verify(entity.getBody().toFlowable(BackpressureStrategy.BUFFER)); } @Test @@ -192,10 +188,9 @@ public class HttpEntityArgumentResolverTests { ResolvableType type = httpEntityType(forClassWithGenerics(Flowable.class, String.class)); HttpEntity> entity = resolveValueWithEmptyBody(type); - TestSubscriber.subscribe(entity.getBody()) - .assertNoError() - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create().expectNextCount(0) + .expectComplete().verify(entity.getBody()); } @Test @@ -266,7 +261,13 @@ public class HttpEntityArgumentResolverTests { HttpEntity> httpEntity = resolveValue(type, body); assertEquals(this.request.getHeaders(), httpEntity.getHeaders()); - TestSubscriber.subscribe(httpEntity.getBody()).assertValues("line1\n", "line2\n", "line3\n"); + ScriptedSubscriber + .create() + .expectNext("line1\n") + .expectNext("line2\n") + .expectNext("line3\n") + .expectComplete() + .verify(httpEntity.getBody()); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java index e44496f474..e69786f462 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageReaderArgumentResolverTests.java @@ -33,6 +33,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import rx.Observable; import rx.Single; @@ -45,7 +46,6 @@ import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.validation.Errors; import org.springframework.validation.Validator; import org.springframework.validation.annotation.Validated; @@ -102,8 +102,7 @@ public class MessageReaderArgumentResolverTests { MethodParameter param = this.testMethod.resolveParam(type); Mono result = this.resolver.readBody(param, true, this.bindingContext, this.exchange); - TestSubscriber.subscribe(result) - .assertError(UnsupportedMediaTypeStatusException.class); + ScriptedSubscriber.create().expectError(UnsupportedMediaTypeStatusException.class).verify(result); } // More extensive "empty body" tests in RequestBody- and HttpEntityArgumentResolverTests @@ -116,7 +115,7 @@ public class MessageReaderArgumentResolverTests { Mono result = (Mono) this.resolver.readBody( param, true, this.bindingContext, this.exchange).block(); - TestSubscriber.subscribe(result).assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectError(ServerWebInputException.class).verify(result); } @Test @@ -263,9 +262,7 @@ public class MessageReaderArgumentResolverTests { MethodParameter param = this.testMethod.resolveParam(type); Mono mono = resolveValue(param, body); - TestSubscriber.subscribe(mono) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0).expectError(ServerWebInputException.class).verify(mono); } @Test @SuppressWarnings("unchecked") @@ -275,16 +272,17 @@ public class MessageReaderArgumentResolverTests { MethodParameter param = this.testMethod.resolveParam(type); Flux flux = resolveValue(param, body); - TestSubscriber.subscribe(flux) - .assertValues(new TestBean("f1", "b1")) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create() + .expectNext(new TestBean("f1", "b1")) + .expectError(ServerWebInputException.class) + .verify(flux); } @Test // SPR-9964 public void parameterizedMethodArgument() throws Exception { Method method = AbstractParameterizedController.class.getMethod("handleDto", Identifiable.class); - HandlerMethod handlerMethod = new HandlerMethod(new ConcreteParameterizedController(), method); - MethodParameter methodParam = handlerMethod.getMethodParameters()[0]; + HandlerMethod handlerMethod = new HandlerMethod(new ConcreteParameterizedController(), method); + MethodParameter methodParam = handlerMethod.getMethodParameters()[0]; SimpleBean simpleBean = resolveValue(methodParam, "{\"name\" : \"Jad\"}"); assertEquals("Jad", simpleBean.getName()); @@ -417,7 +415,7 @@ public class MessageReaderArgumentResolverTests { void setId(Long id); } - @SuppressWarnings({ "serial" }) + @SuppressWarnings({"serial"}) private static class SimpleBean implements Identifiable { private Long id; diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java index b1ec3977bb..70abad8ae0 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/MessageWriterResultHandlerTests.java @@ -33,6 +33,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import rx.Completable; import rx.Observable; @@ -42,6 +43,7 @@ import org.springframework.core.codec.ByteBufferEncoder; import org.springframework.core.codec.CharSequenceEncoder; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.HttpMethod; import org.springframework.http.codec.EncoderHttpMessageWriter; @@ -52,7 +54,6 @@ import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ObjectUtils; import org.springframework.web.reactive.accept.RequestedContentTypeResolver; import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; @@ -136,7 +137,7 @@ public class MessageWriterResultHandlerTests { HttpMessageWriter writer = new EncoderHttpMessageWriter<>(new ByteBufferEncoder()); Mono mono = createResultHandler(writer).writeBody(body, returnType(type), this.exchange); - TestSubscriber.subscribe(mono).assertError(IllegalStateException.class); + ScriptedSubscriber.create().expectError(IllegalStateException.class).verify(mono); } @Test // SPR-12811 @@ -193,9 +194,11 @@ public class MessageWriterResultHandlerTests { } private void assertResponseBody(String responseBody) { - TestSubscriber.subscribe(this.response.getBody()) - .assertValuesWith(buf -> assertEquals(responseBody, - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> assertEquals(responseBody, + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))) + .expectComplete() + .verify(this.response.getBody()); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java index 7828a07bc8..8c5ba5b7f5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolverTests.java @@ -24,6 +24,7 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.SynthesizingMethodParameter; @@ -32,7 +33,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -134,35 +134,40 @@ public class PathVariableMethodArgumentResolverTests { public void handleMissingValue() throws Exception { BindingContext bindingContext = new BindingContext(); Mono mono = this.resolver.resolveArgument(this.paramNamedString, bindingContext, this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerErrorException.class); + ScriptedSubscriber + .create().expectNextCount(0) + .expectError(ServerErrorException.class) + .verify(mono); } @Test public void nullIfNotRequired() throws Exception { BindingContext bindingContext = new BindingContext(); Mono mono = this.resolver.resolveArgument(this.paramNotRequired, bindingContext, this.exchange); - TestSubscriber - .subscribe(mono) - .assertComplete() - .assertNoValues(); + ScriptedSubscriber + .create().expectNextCount(0) + .expectComplete() + .verify(mono); } @Test public void wrapEmptyWithOptional() throws Exception { BindingContext bindingContext = new BindingContext(); Mono mono = this.resolver.resolveArgument(this.paramOptional, bindingContext, this.exchange); - Object result = mono.block(); - TestSubscriber - .subscribe(mono) - .assertValues(Optional.empty()); + + ScriptedSubscriber.create() + .consumeNextWith(value -> { + assertTrue(value instanceof Optional); + assertFalse(((Optional) value).isPresent()); + }) + .expectComplete() + .verify(mono); } @SuppressWarnings("unused") public void handle(@PathVariable(value = "name") String param1, String param2, - @PathVariable(name="name", required = false) String param3, + @PathVariable(name = "name", required = false) String param3, @PathVariable("name") Optional param4) { } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java index 8dccb347dd..0afbd86dfa 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestAttributeMethodArgumentResolverTests.java @@ -21,6 +21,7 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -32,7 +33,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -89,9 +89,9 @@ public class RequestAttributeMethodArgumentResolverTests { public void resolve() throws Exception { MethodParameter param = initMethodParameter(0); Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(mono); Foo foo = new Foo(); this.exchange.getAttributes().put("foo", foo); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java index e8e00a234f..3566644051 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestBodyArgumentResolverTests.java @@ -26,6 +26,8 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; +import rx.Completable; import rx.Observable; import rx.RxReactiveStreams; import rx.Single; @@ -38,7 +40,6 @@ import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.HttpMessageReader; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.reactive.result.ResolvableMethod; import org.springframework.web.reactive.result.method.BindingContext; @@ -124,26 +125,26 @@ public class RequestBodyArgumentResolverTests { public void emptyBodyWithMono() throws Exception { ResolvableType type = forClassWithGenerics(Mono.class, String.class); - TestSubscriber.subscribe(resolveValueWithEmptyBody(type, true)) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify((Mono) resolveValueWithEmptyBody(type, true)); - TestSubscriber.subscribe(resolveValueWithEmptyBody(type, false)) - .assertNoValues() - .assertComplete(); + ScriptedSubscriber.create().expectNextCount(0) + .expectComplete() + .verify((Mono) resolveValueWithEmptyBody(type, false)); } @Test public void emptyBodyWithFlux() throws Exception { ResolvableType type = forClassWithGenerics(Flux.class, String.class); - TestSubscriber.subscribe(resolveValueWithEmptyBody(type, true)) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify((Flux) resolveValueWithEmptyBody(type, true)); - TestSubscriber.subscribe(resolveValueWithEmptyBody(type, false)) - .assertNoValues() - .assertComplete(); + ScriptedSubscriber.create().expectNextCount(0) + .expectComplete() + .verify((Flux) resolveValueWithEmptyBody(type, false)); } @Test @@ -151,14 +152,14 @@ public class RequestBodyArgumentResolverTests { ResolvableType type = forClassWithGenerics(Single.class, String.class); Single single = resolveValueWithEmptyBody(type, true); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(single)) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(RxReactiveStreams.toPublisher(single)); single = resolveValueWithEmptyBody(type, false); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(single)) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(RxReactiveStreams.toPublisher(single)); } @Test @@ -166,14 +167,14 @@ public class RequestBodyArgumentResolverTests { ResolvableType type = forClassWithGenerics(Observable.class, String.class); Observable observable = resolveValueWithEmptyBody(type, true); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(observable)) - .assertNoValues() - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(RxReactiveStreams.toPublisher(observable)); observable = resolveValueWithEmptyBody(type, false); - TestSubscriber.subscribe(RxReactiveStreams.toPublisher(observable)) - .assertNoValues() - .assertComplete(); + ScriptedSubscriber.create().expectNextCount(0) + .expectComplete() + .verify(RxReactiveStreams.toPublisher(observable)); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java index b88155c620..4907b99cdd 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestHeaderMethodArgumentResolverTests.java @@ -26,6 +26,7 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.MethodParameter; @@ -35,7 +36,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -203,9 +203,9 @@ public class RequestHeaderMethodArgumentResolverTests { Mono mono = resolver.resolveArgument( this.paramNamedValueStringArray, this.bindingContext, this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(mono); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java index d19f1f1924..46918ed688 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java @@ -24,6 +24,7 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; @@ -34,7 +35,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -159,9 +159,9 @@ public class RequestParamMethodArgumentResolverTests { Mono mono = this.resolver.resolveArgument( this.paramNamedStringArray, this.bindingContext, this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(ServerWebInputException.class) + .verify(mono); } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java index 97eeef21bd..4861dee9e5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java @@ -29,6 +29,7 @@ import java.util.concurrent.CompletableFuture; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import rx.Completable; import rx.Single; @@ -36,6 +37,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.core.codec.ByteBufferEncoder; import org.springframework.core.codec.CharSequenceEncoder; +import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -48,7 +50,6 @@ import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ObjectUtils; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.accept.RequestedContentTypeResolver; @@ -64,8 +65,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.core.ResolvableType.forClassWithGenerics; -import static org.springframework.http.ResponseEntity.ok; import static org.springframework.http.ResponseEntity.notFound; +import static org.springframework.http.ResponseEntity.ok; /** * Unit tests for {@link ResponseEntityResultHandler}. When adding a test also @@ -113,7 +114,8 @@ public class ResponseEntityResultHandlerTests { } - @Test @SuppressWarnings("ConstantConditions") + @Test + @SuppressWarnings("ConstantConditions") public void supports() throws NoSuchMethodException { Object value = null; @@ -201,7 +203,7 @@ public class ResponseEntityResultHandlerTests { @Test public void handleReturnValueLastModified() throws Exception { Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); - Instant oneMinAgo = currentTime.minusSeconds(60); + Instant oneMinAgo = currentTime.minusSeconds(60); this.request.getHeaders().setIfModifiedSince(currentTime.toEpochMilli()); ResponseEntity entity = ok().lastModified(oneMinAgo.toEpochMilli()).body("body"); @@ -241,7 +243,7 @@ public class ResponseEntityResultHandlerTests { this.request.getHeaders().setIfNoneMatch(eTag); Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); - Instant oneMinAgo = currentTime.minusSeconds(60); + Instant oneMinAgo = currentTime.minusSeconds(60); this.request.getHeaders().setIfModifiedSince(currentTime.toEpochMilli()); ResponseEntity entity = ok().eTag(eTag).lastModified(oneMinAgo.toEpochMilli()).body("body"); @@ -258,7 +260,7 @@ public class ResponseEntityResultHandlerTests { this.request.getHeaders().setIfNoneMatch(etag); Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); - Instant oneMinAgo = currentTime.minusSeconds(60); + Instant oneMinAgo = currentTime.minusSeconds(60); this.request.getHeaders().setIfModifiedSince(currentTime.toEpochMilli()); ResponseEntity entity = ok().eTag(newEtag).lastModified(oneMinAgo.toEpochMilli()).body("body"); @@ -289,12 +291,14 @@ public class ResponseEntityResultHandlerTests { } private void assertResponseBody(String responseBody) { - TestSubscriber.subscribe(this.response.getBody()) - .assertValuesWith(buf -> assertEquals(responseBody, - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> assertEquals(responseBody, + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))) + .expectComplete() + .verify(this.response.getBody()); } - private void assertConditionalResponse(HttpStatus status, String body, String etag, Instant lastModified) { + private void assertConditionalResponse(HttpStatus status, String body, String etag, Instant lastModified) throws Exception { assertEquals(status, this.response.getStatusCode()); if (body != null) { assertResponseBody(body); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java index 71c6048105..322d019703 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SessionAttributeMethodArgumentResolverTests.java @@ -21,6 +21,7 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -32,7 +33,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.annotation.SessionAttribute; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; @@ -96,9 +96,7 @@ public class SessionAttributeMethodArgumentResolverTests { public void resolve() throws Exception { MethodParameter param = initMethodParameter(0); Mono mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange); - TestSubscriber - .subscribe(mono) - .assertError(ServerWebInputException.class); + ScriptedSubscriber.create().expectError(ServerWebInputException.class).verify(mono); Foo foo = new Foo(); when(this.session.getAttribute("foo")).thenReturn(Optional.of(foo)); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java index 9401a8913b..2566068011 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java @@ -32,7 +32,7 @@ import org.springframework.http.codec.BodyExtractors; import org.springframework.http.codec.ServerSentEvent; import org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests; import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.tests.TestSubscriber; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.reactive.ClientRequest; @@ -87,10 +87,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { .map(s -> (s.replace("\n", ""))) .take(2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues("data:foo 0", "data:foo 1"); + ScriptedSubscriber.create() + .expectNext("data:foo 0") + .expectNext("data:foo 1") + .expectComplete() + .verify(result, Duration.ofSeconds(5L)); } @Test public void sseAsPerson() throws Exception { @@ -108,10 +109,10 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { .takeUntil(s -> s.endsWith("foo 1\"}")) .reduce((s1, s2) -> s1 + s2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues("data:{\"name\":\"foo 0\"}data:{\"name\":\"foo 1\"}"); + ScriptedSubscriber.create() + .expectNext("data:{\"name\":\"foo 0\"}data:{\"name\":\"foo 1\"}") + .expectComplete() + .verify(result, Duration.ofSeconds(5L)); } @Test @@ -128,13 +129,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { .map(s -> s.replace("\n", "")) .take(2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues( - "id:0:bardata:foo", - "id:1:bardata:foo" - ); + ScriptedSubscriber.create() + .expectNext("id:0:bardata:foo") + .expectNext("id:1:bardata:foo") + .expectComplete() + .verify(result, Duration.ofSeconds(5L)); } @Test @@ -152,13 +151,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { .map(s -> s.replace("\n", "")) .take(2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues( - "id:0:bardata:foo", - "id:1:bardata:foo" - ); + ScriptedSubscriber.create() + .expectNext("id:0:bardata:foo") + .expectNext("id:1:bardata:foo") + .expectComplete() + .verify(result, Duration.ofSeconds(5L)); } @RestController diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java index dd0c2e65c2..ffa274fbcc 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/HttpMessageWriterViewTests.java @@ -26,8 +26,10 @@ import java.util.List; import java.util.Map; import org.junit.Test; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.codec.CharSequenceEncoder; +import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -35,7 +37,6 @@ import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ModelMap; import org.springframework.util.MimeType; @@ -45,7 +46,10 @@ import org.springframework.web.server.session.DefaultWebSessionManager; import org.springframework.web.server.session.WebSessionManager; import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; /** @@ -151,10 +155,12 @@ public class HttpMessageWriterViewTests { this.view.render(this.model, MediaType.APPLICATION_JSON, exchange); - TestSubscriber - .subscribe(response.getBody()) - .assertValuesWith(buf -> assertEquals("{\"foo\":\"f\",\"bar\":\"b\"}", - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith( buf -> assertEquals("{\"foo\":\"f\",\"bar\":\"b\"}", + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8)) + ) + .expectComplete() + .verify(response.getBody()); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java index 6c68cebf61..e67a2a9b65 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java @@ -31,6 +31,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import rx.Completable; import rx.Single; @@ -42,10 +43,9 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; @@ -180,7 +180,7 @@ public class ViewResolutionResultHandlerTests { ModelMap model = new ExtendedModelMap().addAttribute("id", "123"); HandlerResult result = new HandlerResult(new Object(), returnValue, returnType(type), model); - ViewResolutionResultHandler handler = createResultHandler(new TestViewResolver("account")); + ViewResolutionResultHandler handler = createResultHandler(new TestViewResolver("account")); this.request.setUri("/account"); handler.handleResult(this.exchange, result).block(Duration.ofSeconds(5)); @@ -204,7 +204,9 @@ public class ViewResolutionResultHandlerTests { this.request.setUri("/path"); Mono mono = createResultHandler().handleResult(this.exchange, handlerResult); - TestSubscriber.subscribe(mono).assertErrorMessage("Could not resolve view with name 'account'."); + ScriptedSubscriber.create().expectNextCount(0) + .expectErrorWith(err -> err.getMessage().equals("Could not resolve view with name 'account'.")) + .verify(mono); } @Test @@ -237,7 +239,9 @@ public class ViewResolutionResultHandlerTests { ViewResolutionResultHandler resultHandler = createResultHandler(new TestViewResolver("account")); Mono mono = resultHandler.handleResult(this.exchange, handlerResult); - TestSubscriber.subscribe(mono).assertError(NotAcceptableStatusException.class); + ScriptedSubscriber.create().expectNextCount(0) + .expectError(NotAcceptableStatusException.class) + .verify(mono); } @@ -271,7 +275,7 @@ public class ViewResolutionResultHandlerTests { private void testHandle(String path, ResolvableType returnType, Object returnValue, String responseBody, ViewResolver... resolvers) throws URISyntaxException { - testHandle(path, ResolvableMethod.onClass(TestController.class).returning(returnType), + testHandle(path, ResolvableMethod.onClass(TestController.class).returning(returnType), returnValue, responseBody, resolvers); } @@ -287,9 +291,11 @@ public class ViewResolutionResultHandlerTests { } private void assertResponseBody(String responseBody) { - TestSubscriber.subscribe(this.response.getBody()) - .assertValuesWith(buf -> assertEquals(responseBody, - DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> assertEquals(responseBody, + DataBufferTestUtils.dumpString(buf, StandardCharsets.UTF_8))) + .expectComplete() + .verify(this.response.getBody()); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerViewTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerViewTests.java index 465b181837..2e7d43e187 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerViewTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerViewTests.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.context.ApplicationContextException; import org.springframework.context.support.GenericApplicationContext; @@ -32,7 +33,6 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ModelMap; import org.springframework.web.server.ServerWebExchange; @@ -123,10 +123,12 @@ public class FreeMarkerViewTests { model.addAttribute("hello", "hi FreeMarker"); view.render(model, null, this.exchange); - TestSubscriber - .subscribe(this.response.getBody()) - .assertValuesWith(dataBuffer -> - assertEquals("hi FreeMarker", asString(dataBuffer))); + ScriptedSubscriber.create() + .consumeNextWith(buf -> { + assertEquals("hi FreeMarker", asString(buf)); + }) + .expectComplete() + .verify(this.response.getBody()); } diff --git a/spring-web/src/test/java/org/springframework/http/codec/BodyExtractorsTests.java b/spring-web/src/test/java/org/springframework/http/codec/BodyExtractorsTests.java index b7ae0b39f5..69dc6af7e4 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/BodyExtractorsTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/BodyExtractorsTests.java @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.codec.ByteBufferDecoder; import org.springframework.core.codec.StringDecoder; @@ -39,7 +40,7 @@ import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.xml.Jaxb2XmlDecoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; -import org.springframework.tests.TestSubscriber; +import org.springframework.web.server.UnsupportedMediaTypeStatusException; /** * @author Arjen Poutsma @@ -79,9 +80,10 @@ public class BodyExtractorsTests { Mono result = extractor.extract(request, this.context); - TestSubscriber.subscribe(result) - .assertComplete() - .assertValues("foo"); + ScriptedSubscriber.create() + .expectNext("foo") + .expectComplete() + .verify(result); } @Test @@ -97,9 +99,11 @@ public class BodyExtractorsTests { request.setBody(body); Flux result = extractor.extract(request, this.context); - TestSubscriber.subscribe(result) - .assertComplete() - .assertValues("foo"); + + ScriptedSubscriber.create() + .expectNext("foo") + .expectComplete() + .verify(result); } @Test @@ -123,8 +127,9 @@ public class BodyExtractorsTests { }; Flux result = extractor.extract(request, emptyContext); - TestSubscriber.subscribe(result) - .assertError(UnsupportedMediaTypeException.class); + ScriptedSubscriber.create() + .expectError(UnsupportedMediaTypeException.class) + .verify(result); } } \ No newline at end of file diff --git a/spring-web/src/test/java/org/springframework/http/codec/BodyInsertersTests.java b/spring-web/src/test/java/org/springframework/http/codec/BodyInsertersTests.java index 622f26dd36..c6afe90dcc 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/BodyInsertersTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/BodyInsertersTests.java @@ -27,6 +27,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.codec.ByteBufferEncoder; import org.springframework.core.codec.CharSequenceEncoder; @@ -39,7 +40,6 @@ import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.xml.Jaxb2XmlEncoder; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertArrayEquals; @@ -79,14 +79,14 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, this.context); - TestSubscriber.subscribe(result) - .assertComplete(); + ScriptedSubscriber.create().expectComplete().verify(result); ByteBuffer byteBuffer = ByteBuffer.wrap(body.getBytes(UTF_8)); DataBuffer buffer = new DefaultDataBufferFactory().wrap(byteBuffer); - TestSubscriber.subscribe(response.getBody()) - .assertComplete() - .assertValues(buffer); + ScriptedSubscriber.create() + .expectNext(buffer) + .expectComplete() + .verify(response.getBody()); } @Test @@ -98,14 +98,14 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, this.context); - TestSubscriber.subscribe(result) - .assertComplete(); + ScriptedSubscriber.create().expectComplete().verify(result); ByteBuffer byteBuffer = ByteBuffer.wrap("foo".getBytes(UTF_8)); DataBuffer buffer = new DefaultDataBufferFactory().wrap(byteBuffer); - TestSubscriber.subscribe(response.getBody()) - .assertComplete() - .assertValues(buffer); + ScriptedSubscriber.create() + .expectNext(buffer) + .expectComplete() + .verify(response.getBody()); } @Test @@ -117,18 +117,18 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, this.context); - TestSubscriber.subscribe(result) - .assertComplete(); + ScriptedSubscriber.create().expectComplete().verify(result); byte[] expectedBytes = Files.readAllBytes(body.getFile().toPath()); - TestSubscriber.subscribe(response.getBody()) - .assertComplete() - .assertValuesWith(dataBuffer -> { + ScriptedSubscriber.create() + .consumeNextWith(dataBuffer -> { byte[] resultBytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(resultBytes); assertArrayEquals(expectedBytes, resultBytes); - }); + }) + .expectComplete() + .verify(response.getBody()); } @Test @@ -142,9 +142,7 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, this.context); - TestSubscriber.subscribe(result) - .assertComplete(); - + ScriptedSubscriber.create().expectNextCount(0).expectComplete().verify(result); } @Test @@ -157,9 +155,7 @@ public class BodyInsertersTests { MockServerHttpResponse response = new MockServerHttpResponse(); Mono result = inserter.insert(response, this.context); - TestSubscriber.subscribe(result) - .assertComplete(); - + ScriptedSubscriber.create().expectNextCount(0).expectComplete().verify(result); } } \ No newline at end of file diff --git a/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java b/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java index 97d518e03a..e9dcda0bb0 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java +++ b/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java @@ -15,26 +15,25 @@ */ package org.springframework.http.codec; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.junit.Assert.*; -import static org.hamcrest.Matchers.*; - import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.Collections; import org.jetbrains.annotations.NotNull; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.codec.ByteBufferEncoder; import org.springframework.core.codec.Encoder; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; +import static java.nio.charset.StandardCharsets.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + /** * Unit tests for {@link EncoderHttpMessageWriter}. * @@ -69,7 +68,10 @@ public class EncoderHttpMessageWriterTest { MediaType.APPLICATION_OCTET_STREAM, this.response, Collections.emptyMap()); assertThat(this.response.getHeaders().getContentType(), is(MediaType.APPLICATION_OCTET_STREAM)); - TestSubscriber.subscribe(this.response.getBodyAsString()).assertComplete().assertValues(payload); + ScriptedSubscriber.create() + .expectNext(payload) + .expectComplete() + .verify(this.response.getBodyAsString()); } @NotNull diff --git a/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java index 7c0b1eaf4f..a9be6de4a2 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java @@ -22,6 +22,7 @@ import java.util.Collections; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; @@ -32,7 +33,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import static org.hamcrest.Matchers.*; @@ -69,23 +69,38 @@ public class ResourceHttpMessageWriterTests { @Test public void shouldWriteResource() throws Exception { - TestSubscriber.subscribe(this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class), - MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap())).assertComplete(); + + Mono mono = this.writer.write(Mono.just(resource), null, + ResolvableType.forClass(Resource.class), + MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap()); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete() + .verify(mono); assertThat(this.response.getHeaders().getContentType(), is(MediaType.TEXT_PLAIN)); assertThat(this.response.getHeaders().getContentLength(), is(39L)); assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES), is("bytes")); Mono result = this.response.getBodyAsString(); - TestSubscriber.subscribe(result).assertComplete().assertValues("Spring Framework test resource content."); + ScriptedSubscriber + .create() + .expectNext("Spring Framework test resource content.") + .expectComplete() + .verify(result); } @Test public void shouldWriteResourceRange() throws Exception { this.request.getHeaders().setRange(Collections.singletonList(HttpRange.createByteRange(0, 5))); - - TestSubscriber.subscribe(this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class), - MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap())).assertComplete(); + Mono mono = this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class), + MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap()); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete() + .verify(mono); assertThat(this.response.getHeaders().getContentType(), is(MediaType.TEXT_PLAIN)); assertThat(this.response.getHeaders().getFirst(HttpHeaders.CONTENT_RANGE), is("bytes 0-5/39")); @@ -93,15 +108,24 @@ public class ResourceHttpMessageWriterTests { assertThat(this.response.getHeaders().getContentLength(), is(6L)); Mono result = this.response.getBodyAsString(); - TestSubscriber.subscribe(result).assertComplete().assertValues("Spring"); + ScriptedSubscriber + .create() + .expectNext("Spring") + .expectComplete() + .verify(result); } @Test public void shouldSetRangeNotSatisfiableStatus() throws Exception { this.request.getHeaders().set(HttpHeaders.RANGE, "invalid"); - TestSubscriber.subscribe(this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class), - MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap())); + Mono mono = this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class), + MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap()); + ScriptedSubscriber + .create() + .expectNextCount(0) + .expectComplete() + .verify(mono); assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES), is("bytes")); assertThat(this.response.getStatusCode(), is(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE)); diff --git a/spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java index c5b60da7c8..bc73800076 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java @@ -16,8 +16,6 @@ package org.springframework.http.codec; -import static org.junit.Assert.*; -import static org.hamcrest.Matchers.*; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -30,6 +28,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; @@ -38,10 +37,12 @@ import org.springframework.core.io.support.ResourceRegion; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.util.MimeTypeUtils; import org.springframework.util.StringUtils; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + /** * Unit tests for {@link ResourceRegionHttpMessageWriter}. * @author Brian Clozel @@ -82,15 +83,16 @@ public class ResourceRegionHttpMessageWriterTests { ResourceRegion region = new ResourceRegion(this.resource, 0, 6); - TestSubscriber.subscribe(this.writer.write(Mono.just(region), ResolvableType.forClass(ResourceRegion.class), - MediaType.TEXT_PLAIN, this.response, Collections.emptyMap())).assertComplete(); + Mono mono = this.writer.write(Mono.just(region), ResolvableType.forClass(ResourceRegion.class), + MediaType.TEXT_PLAIN, this.response, Collections.emptyMap()); + ScriptedSubscriber.create().expectComplete().verify(mono); assertThat(this.response.getHeaders().getContentType(), is(MediaType.TEXT_PLAIN)); assertThat(this.response.getHeaders().getFirst(HttpHeaders.CONTENT_RANGE), is("bytes 0-5/39")); assertThat(this.response.getHeaders().getContentLength(), is(6L)); Mono result = response.getBodyAsString(); - TestSubscriber.subscribe(result).assertComplete().assertValues("Spring"); + ScriptedSubscriber.create().expectNext("Spring").expectComplete().verify(result); } @Test @@ -105,43 +107,43 @@ public class ResourceRegionHttpMessageWriterTests { Map hints = new HashMap<>(1); hints.put(ResourceRegionHttpMessageWriter.BOUNDARY_STRING_HINT, boundary); - TestSubscriber.subscribe( - this.writer.write(regions, ResolvableType.forClass(ResourceRegion.class), - MediaType.TEXT_PLAIN, this.response, hints)) - .assertComplete(); + Mono mono = this.writer.write(regions, ResolvableType.forClass(ResourceRegion.class), + MediaType.TEXT_PLAIN, this.response, hints); + ScriptedSubscriber.create().expectComplete().verify(mono); HttpHeaders headers = this.response.getHeaders(); assertThat(headers.getContentType().toString(), startsWith("multipart/byteranges;boundary=" + boundary)); Mono result = response.getBodyAsString(); - TestSubscriber - .subscribe(result).assertNoError() - .assertComplete() - .assertValuesWith(content -> { - String[] ranges = StringUtils.tokenizeToStringArray(content, "\r\n", false, true); - assertThat(ranges[0], is("--" + boundary)); - assertThat(ranges[1], is("Content-Type: text/plain")); - assertThat(ranges[2], is("Content-Range: bytes 0-5/39")); - assertThat(ranges[3], is("Spring")); - - assertThat(ranges[4], is("--" + boundary)); - assertThat(ranges[5], is("Content-Type: text/plain")); - assertThat(ranges[6], is("Content-Range: bytes 7-15/39")); - assertThat(ranges[7], is("Framework")); - - assertThat(ranges[8], is("--" + boundary)); - assertThat(ranges[9], is("Content-Type: text/plain")); - assertThat(ranges[10], is("Content-Range: bytes 17-20/39")); - assertThat(ranges[11], is("test")); - - assertThat(ranges[12], is("--" + boundary)); - assertThat(ranges[13], is("Content-Type: text/plain")); - assertThat(ranges[14], is("Content-Range: bytes 22-38/39")); - assertThat(ranges[15], is("resource content.")); - - assertThat(ranges[16], is("--" + boundary + "--")); - }); + ScriptedSubscriber + .create() + .consumeNextWith(content -> { + String[] ranges = StringUtils + .tokenizeToStringArray(content, "\r\n", false, true); + String[] expected = new String[] { + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 0-5/39", + "Spring", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 7-15/39", + "Framework", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 17-20/39", + "test", + "--" + boundary, + "Content-Type: text/plain", + "Content-Range: bytes 22-38/39", + "resource content.", + "--" + boundary + "--" + }; + assertArrayEquals(expected, ranges); + }) + .expectComplete() + .verify(result); } } 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 a6cf9927b9..83527b492e 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 @@ -18,11 +18,13 @@ package org.springframework.http.codec; import java.time.Duration; import java.util.Collections; +import java.util.function.Consumer; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; @@ -30,7 +32,6 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.MediaType; import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -71,17 +72,13 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll messageWriter.write(source, ResolvableType.forClass(ServerSentEvent.class), new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()); - Publisher> result = outputMessage.getBodyWithFlush(); - TestSubscriber.subscribe(result). - assertNoError(). - assertValuesWith(publisher -> { - TestSubscriber.subscribe(publisher).assertNoError().assertValuesWith( - stringConsumer("id:c42\n" + "event:foo\n" + "retry:123\n" + - ":bla\n:bla bla\n:bla bla bla\n" + - "data:bar\n"), - stringConsumer("\n")); - - }); + Publisher> result = Flux.from(outputMessage.getBodyWithFlush()); + ScriptedSubscriber + .>create() + .consumeNextWith(sseConsumer("id:c42\n" + "event:foo\n" + "retry:123\n" + + ":bla\n:bla bla\n:bla bla bla\n" + "data:bar\n")) + .expectComplete() + .verify(result); } @Test @@ -92,19 +89,12 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()); Publisher> result = outputMessage.getBodyWithFlush(); - TestSubscriber.subscribe(result). - assertNoError(). - assertValuesWith(publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:foo\n"), - stringConsumer("\n")); - - }, publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:bar\n"), - stringConsumer("\n")); - - }); + ScriptedSubscriber + .>create() + .consumeNextWith(sseConsumer("data:foo\n")) + .consumeNextWith(sseConsumer("data:bar\n")) + .expectComplete() + .verify(result); } @Test @@ -115,19 +105,12 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()); Publisher> result = outputMessage.getBodyWithFlush(); - TestSubscriber.subscribe(result). - assertNoError(). - assertValuesWith(publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:foo\ndata:bar\n"), - stringConsumer("\n")); - - }, publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:foo\ndata:baz\n"), - stringConsumer("\n")); - - }); + ScriptedSubscriber + .>create() + .consumeNextWith(sseConsumer("data:foo\ndata:bar\n")) + .consumeNextWith(sseConsumer("data:foo\ndata:baz\n")) + .expectComplete() + .verify(result); } @Test @@ -139,21 +122,22 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()); Publisher> result = outputMessage.getBodyWithFlush(); - TestSubscriber.subscribe(result). - assertNoError(). - assertValuesWith(publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:"), stringConsumer( - "{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"), - stringConsumer("\n"), stringConsumer("\n")); + ScriptedSubscriber + .>create() + .consumeNextWith(sseConsumer("data:", "{\"foo\":\"foofoo\",\"bar\":\"barbar\"}", "\n")) + .consumeNextWith(sseConsumer("data:", "{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}", "\n")) + .expectComplete() + .verify(result); + } - }, publisher -> { - TestSubscriber.subscribe(publisher).assertNoError() - .assertValuesWith(stringConsumer("data:"), stringConsumer( - "{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}"), - stringConsumer("\n"), stringConsumer("\n")); - - }); + private Consumer> sseConsumer(String... expected) { + return publisher -> { + ScriptedSubscriber.StepBuilder builder = ScriptedSubscriber.create(); + for (String value : expected) { + builder = builder.consumeNextWith(stringConsumer(value)); + } + builder.consumeNextWith(stringConsumer("\n")).expectComplete().verify(publisher); + }; } } diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java index 96aac02d0c..2b0362baec 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java @@ -25,15 +25,17 @@ import com.fasterxml.jackson.annotation.JsonView; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.MediaType; import org.springframework.http.codec.Pojo; -import org.springframework.tests.TestSubscriber; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; /** * Unit tests for {@link Jackson2JsonDecoder}. @@ -53,18 +55,20 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa } @Test - public void decodePojo() { + public void decodePojo() throws Exception { Flux source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}")); ResolvableType elementType = ResolvableType.forClass(Pojo.class); Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, Collections.emptyMap()); - TestSubscriber.subscribe(flux).assertNoError().assertComplete(). - assertValues(new Pojo("foofoo", "barbar")); + ScriptedSubscriber.create() + .expectNext(new Pojo("foofoo", "barbar")) + .expectComplete() + .verify(flux); } @Test - public void decodeToList() { + public void decodeToList() throws Exception { Flux source = Flux.just(stringBuffer( "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]")); @@ -72,12 +76,14 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa Mono mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, null, Collections.emptyMap()); - TestSubscriber.subscribe(mono).assertNoError().assertComplete(). - assertValues(Arrays.asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))); + ScriptedSubscriber.create() + .expectNext(Arrays.asList(new Pojo("f1", "b1"), new Pojo("f2", "b2"))) + .expectComplete() + .verify(mono); } @Test - public void decodeToFlux() { + public void decodeToFlux() throws Exception { Flux source = Flux.just(stringBuffer( "[{\"bar\":\"b1\",\"foo\":\"f1\"},{\"bar\":\"b2\",\"foo\":\"f2\"}]")); @@ -85,41 +91,43 @@ public class Jackson2JsonDecoderTests extends AbstractDataBufferAllocatingTestCa Flux flux = new Jackson2JsonDecoder().decode(source, elementType, null, Collections.emptyMap()); - TestSubscriber.subscribe(flux).assertNoError().assertComplete(). - assertValues(new Pojo("f1", "b1"), new Pojo("f2", "b2")); + ScriptedSubscriber.create() + .expectNext(new Pojo("f1", "b1")) + .expectNext(new Pojo("f2", "b2")) + .expectComplete() + .verify(flux); } @Test - public void jsonView() { + public void jsonView() throws Exception { Flux source = Flux.just( stringBuffer("{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}")); - ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); + ResolvableType elementType = ResolvableType.forClass(JacksonViewBean.class); Map hints = Collections.singletonMap(Jackson2JsonDecoder.JSON_VIEW_HINT, MyJacksonView1.class); Flux flux = new Jackson2JsonDecoder() .decode(source, elementType, null, hints).cast(JacksonViewBean.class); - TestSubscriber - .subscribe(flux) - .assertNoError() - .assertComplete() - .assertValuesWith(b -> { + ScriptedSubscriber.create() + .consumeNextWith(b -> { assertTrue(b.getWithView1().equals("with")); assertNull(b.getWithView2()); assertNull(b.getWithoutView()); - }); + }) + .expectComplete() + .verify(flux); } @Test - public void decodeEmptyBodyToMono() { + public void decodeEmptyBodyToMono() throws Exception { Flux source = Flux.empty(); ResolvableType elementType = ResolvableType.forClass(Pojo.class); - Mono flux = new Jackson2JsonDecoder().decodeToMono(source, elementType, + Mono mono = new Jackson2JsonDecoder().decodeToMono(source, elementType, null, Collections.emptyMap()); - TestSubscriber.subscribe(flux) - .assertNoError() - .assertComplete() - .assertValueCount(0); + ScriptedSubscriber. + create().expectNextCount(0) + .expectComplete() + .verify(mono); } diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java index 6b18c9c47c..3644fa10e6 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonEncoderTests.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonView; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; @@ -32,9 +33,9 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.MediaType; import org.springframework.http.codec.Pojo; import org.springframework.http.codec.ServerSentEvent; -import org.springframework.tests.TestSubscriber; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * @author Sebastien Deleuze @@ -55,7 +56,7 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa } @Test - public void encode() { + public void encode() throws Exception { Flux source = Flux.just( new Pojo("foo", "bar"), new Pojo("foofoo", "barbar"), @@ -64,51 +65,52 @@ public class Jackson2JsonEncoderTests extends AbstractDataBufferAllocatingTestCa ResolvableType type = ResolvableType.forClass(Pojo.class); Flux output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap()); - TestSubscriber.subscribe(output) - .assertComplete() - .assertNoError() - .assertValuesWith( - stringConsumer("["), - stringConsumer("{\"foo\":\"foo\",\"bar\":\"bar\"}"), - stringConsumer(","), - stringConsumer("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"), - stringConsumer(","), - stringConsumer("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}"), - stringConsumer("]") - ); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("[")) + .consumeNextWith(stringConsumer("{\"foo\":\"foo\",\"bar\":\"bar\"}")) + .consumeNextWith(stringConsumer(",")) + .consumeNextWith(stringConsumer("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}")) + .consumeNextWith(stringConsumer(",")) + .consumeNextWith(stringConsumer("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}")) + .consumeNextWith(stringConsumer("]")) + .expectComplete() + .verify(output); } @Test - public void encodeWithType() { + public void encodeWithType() throws Exception { Flux source = Flux.just(new Foo(), new Bar()); ResolvableType type = ResolvableType.forClass(ParentClass.class); Flux output = this.encoder.encode(source, this.bufferFactory, type, null, Collections.emptyMap()); - TestSubscriber.subscribe(output) - .assertComplete() - .assertNoError() - .assertValuesWith(stringConsumer("["), - stringConsumer("{\"type\":\"foo\"}"), - stringConsumer(","), - stringConsumer("{\"type\":\"bar\"}"), - stringConsumer("]")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("[")) + .consumeNextWith(stringConsumer("{\"type\":\"foo\"}")) + .consumeNextWith(stringConsumer(",")) + .consumeNextWith(stringConsumer("{\"type\":\"bar\"}")) + .consumeNextWith(stringConsumer("]")) + .expectComplete() + .verify(output); } @Test - public void jsonView() { + public void jsonView() throws Exception { JacksonViewBean bean = new JacksonViewBean(); bean.setWithView1("with"); bean.setWithView2("with"); bean.setWithoutView("without"); - ResolvableType type = ResolvableType.forClass(JacksonViewBean.class); + ResolvableType type = ResolvableType.forClass(JacksonViewBean.class); Map hints = Collections.singletonMap(Jackson2JsonEncoder.JSON_VIEW_HINT, MyJacksonView1.class); Flux output = this.encoder.encode(Mono.just(bean), this.bufferFactory, type, null, hints); - TestSubscriber.subscribe(output) - .assertComplete() - .assertNoError() - .assertValuesWith(stringConsumer("{\"withView1\":\"with\"}")); + ScriptedSubscriber + .create() + .consumeNextWith(stringConsumer("{\"withView1\":\"with\"}")) + .expectComplete() + .verify(output); } diff --git a/spring-web/src/test/java/org/springframework/http/codec/json/JsonObjectDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/json/JsonObjectDecoderTests.java index 7b820e58a8..d9c145e5b0 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/json/JsonObjectDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/json/JsonObjectDecoderTests.java @@ -21,10 +21,10 @@ import java.util.Collections; import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.tests.TestSubscriber; /** * @author Sebastien Deleuze @@ -32,15 +32,16 @@ import org.springframework.tests.TestSubscriber; public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase { @Test - public void decodeSingleChunkToJsonObject() { + public void decodeSingleChunkToJsonObject() throws Exception { JsonObjectDecoder decoder = new JsonObjectDecoder(); Flux source = Flux.just(stringBuffer("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}")); Flux output = decoder.decode(source, null, null, Collections.emptyMap()).map(JsonObjectDecoderTests::toString); - TestSubscriber - .subscribe(output) - .assertValues("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"); + ScriptedSubscriber.create() + .expectNext("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}") + .expectComplete() + .verify(output); } @Test @@ -50,9 +51,10 @@ public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase stringBuffer(", \"bar\": \"barbar\"}")); Flux output = decoder.decode(source, null, null, Collections.emptyMap()).map(JsonObjectDecoderTests::toString); - TestSubscriber - .subscribe(output) - .assertValues("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}"); + ScriptedSubscriber.create() + .expectNext("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}") + .expectComplete() + .verify(output); } @Test @@ -62,10 +64,11 @@ public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase "[{\"foo\": \"foofoo\", \"bar\": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]")); Flux output = decoder.decode(source, null, null, Collections.emptyMap()).map(JsonObjectDecoderTests::toString); - TestSubscriber - .subscribe(output) - .assertValues("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}", - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}"); + ScriptedSubscriber.create() + .expectNext("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}") + .expectNext("{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}") + .expectComplete() + .verify(output); } @Test @@ -76,10 +79,11 @@ public class JsonObjectDecoderTests extends AbstractDataBufferAllocatingTestCase ": \"barbar\"},{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}]")); Flux output = decoder.decode(source, null, null, Collections.emptyMap()).map(JsonObjectDecoderTests::toString); - TestSubscriber - .subscribe(output) - .assertValues("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}", - "{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}"); + ScriptedSubscriber.create() + .expectNext("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}") + .expectNext("{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}") + .expectComplete() + .verify(output); } diff --git a/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlDecoderTests.java index c1642279e3..cff39f4416 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlDecoderTests.java @@ -23,6 +23,7 @@ import javax.xml.stream.events.XMLEvent; import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; @@ -35,9 +36,10 @@ import org.springframework.http.codec.xml.jaxb.XmlRootElementWithNameAndNamespac import org.springframework.http.codec.xml.jaxb.XmlType; import org.springframework.http.codec.xml.jaxb.XmlTypeWithName; import org.springframework.http.codec.xml.jaxb.XmlTypeWithNameAndNamespace; -import org.springframework.tests.TestSubscriber; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * @author Sebastien Deleuze @@ -89,11 +91,8 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { .decode(Flux.just(stringBuffer(POJO_ROOT)), null, null, Collections.emptyMap()); Flux> result = this.decoder.split(xmlEvents, new QName("pojo")); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(events -> { + ScriptedSubscriber.>create() + .consumeNextWith(events -> { assertEquals(8, events.size()); assertStartElement(events.get(0), "pojo"); assertStartElement(events.get(1), "foo"); @@ -103,22 +102,20 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { assertCharacters(events.get(5), "barbar"); assertEndElement(events.get(6), "bar"); assertEndElement(events.get(7), "pojo"); - }); - - + }) + .expectComplete() + .verify(result); } @Test - public void splitMultipleBranches() { + public void splitMultipleBranches() throws Exception { Flux xmlEvents = this.xmlEventDecoder .decode(Flux.just(stringBuffer(POJO_CHILD)), null, null, Collections.emptyMap()); Flux> result = this.decoder.split(xmlEvents, new QName("pojo")); - TestSubscriber - .subscribe(result) - .assertNoError() - .assertComplete() - .assertValuesWith(events -> { + + ScriptedSubscriber.>create() + .consumeNextWith(events -> { assertEquals(8, events.size()); assertStartElement(events.get(0), "pojo"); assertStartElement(events.get(1), "foo"); @@ -128,7 +125,8 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { assertCharacters(events.get(5), "bar"); assertEndElement(events.get(6), "bar"); assertEndElement(events.get(7), "pojo"); - }, events -> { + }) + .consumeNextWith(events -> { assertEquals(8, events.size()); assertStartElement(events.get(0), "pojo"); assertStartElement(events.get(1), "foo"); @@ -138,7 +136,9 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { assertCharacters(events.get(5), "barbar"); assertEndElement(events.get(6), "bar"); assertEndElement(events.get(7), "pojo"); - }); + }) + .expectComplete() + .verify(result); } private static void assertStartElement(XMLEvent event, String expectedLocalName) { @@ -162,11 +162,10 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(Pojo.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValues(new Pojo("foofoo", "barbar")); + ScriptedSubscriber.create() + .expectNext(new Pojo("foofoo", "barbar")) + .expectComplete() + .verify(output); } @Test @@ -175,11 +174,10 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(TypePojo.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValues(new TypePojo("foofoo", "barbar")); + ScriptedSubscriber.create() + .expectNext(new TypePojo("foofoo", "barbar")) + .expectComplete() + .verify(output); } @Test @@ -188,11 +186,11 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(Pojo.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValues(new Pojo("foo", "bar"), new Pojo("foofoo", "barbar")); + ScriptedSubscriber.create() + .expectNext(new Pojo("foo", "bar")) + .expectNext(new Pojo("foofoo", "barbar")) + .expectComplete() + .verify(output); } @Test @@ -201,11 +199,11 @@ public class Jaxb2XmlDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux output = this.decoder.decode(source, ResolvableType.forClass(TypePojo.class), null, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertNoError() - .assertComplete() - .assertValues(new TypePojo("foo", "bar"), new TypePojo("foofoo", "barbar")); + ScriptedSubscriber.create() + .expectNext(new TypePojo("foo", "bar")) + .expectNext(new TypePojo("foofoo", "barbar")) + .expectComplete() + .verify(output); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlEncoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlEncoderTests.java index 502bcfcf4f..958050fbcf 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlEncoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/xml/Jaxb2XmlEncoderTests.java @@ -21,6 +21,7 @@ import java.util.Collections; import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.ResolvableType; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; @@ -29,10 +30,11 @@ 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.Pojo; -import org.springframework.tests.TestSubscriber; -import static org.junit.Assert.*; -import static org.xmlunit.matchers.CompareMatcher.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; /** * @author Sebastien Deleuze @@ -61,24 +63,27 @@ public class Jaxb2XmlEncoderTests extends AbstractDataBufferAllocatingTestCase { } @Test - public void encode() { + public void encode() throws Exception { Flux source = Flux.just(new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar")); Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClass(Pojo.class), - MediaType.APPLICATION_XML, Collections.emptyMap()); - TestSubscriber - .subscribe(output) - .assertValuesWith(dataBuffer -> { - try { - String s = DataBufferTestUtils - .dumpString(dataBuffer, StandardCharsets.UTF_8); - assertThat(s, isSimilarTo("" + - "barbarfoofoo")); - } - finally { - DataBufferUtils.release(dataBuffer); - } - }); + MediaType.APPLICATION_XML, Collections.emptyMap()); + + ScriptedSubscriber + .create() + .consumeNextWith(dataBuffer -> { + try { + String s = DataBufferTestUtils + .dumpString(dataBuffer, StandardCharsets.UTF_8); + assertThat(s, isSimilarTo("" + + "barbarfoofoo")); + } + finally { + DataBufferUtils.release(dataBuffer); + } + }) + .expectComplete() + .verify(output); } } diff --git a/spring-web/src/test/java/org/springframework/http/codec/xml/XmlEventDecoderTests.java b/spring-web/src/test/java/org/springframework/http/codec/xml/XmlEventDecoderTests.java index 03cb2ad5fa..e1918df347 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/xml/XmlEventDecoderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/xml/XmlEventDecoderTests.java @@ -21,9 +21,9 @@ import javax.xml.stream.events.XMLEvent; import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase; -import org.springframework.tests.TestSubscriber; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -47,19 +47,19 @@ public class XmlEventDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux events = this.decoder.decode(Flux.just(stringBuffer(XML)), null, null, Collections.emptyMap()); - TestSubscriber - .subscribe(events) - .assertNoError() - .assertComplete() - .assertValuesWith(e -> assertTrue(e.isStartDocument()), - e -> assertStartElement(e, "pojo"), - e -> assertStartElement(e, "foo"), - e -> assertCharacters(e, "foofoo"), - e -> assertEndElement(e, "foo"), - e -> assertStartElement(e, "bar"), - e -> assertCharacters(e, "barbar"), - e -> assertEndElement(e, "bar"), - e -> assertEndElement(e, "pojo")); + ScriptedSubscriber + .create() + .consumeNextWith(e -> assertTrue(e.isStartDocument())) + .consumeNextWith(e -> assertStartElement(e, "pojo")) + .consumeNextWith(e -> assertStartElement(e, "foo")) + .consumeNextWith(e -> assertCharacters(e, "foofoo")) + .consumeNextWith(e -> assertEndElement(e, "foo")) + .consumeNextWith(e -> assertStartElement(e, "bar")) + .consumeNextWith(e -> assertCharacters(e, "barbar")) + .consumeNextWith(e -> assertEndElement(e, "bar")) + .consumeNextWith(e -> assertEndElement(e, "pojo")) + .expectComplete() + .verify(events); } @Test @@ -69,19 +69,20 @@ public class XmlEventDecoderTests extends AbstractDataBufferAllocatingTestCase { Flux events = this.decoder.decode(Flux.just(stringBuffer(XML)), null, null, Collections.emptyMap()); - TestSubscriber - .subscribe(events) - .assertNoError() - .assertComplete() - .assertValuesWith(e -> assertTrue(e.isStartDocument()), - e -> assertStartElement(e, "pojo"), - e -> assertStartElement(e, "foo"), - e -> assertCharacters(e, "foofoo"), - e -> assertEndElement(e, "foo"), - e -> assertStartElement(e, "bar"), - e -> assertCharacters(e, "barbar"), - e -> assertEndElement(e, "bar"), e -> assertEndElement(e, "pojo"), - e -> assertTrue(e.isEndDocument())); + ScriptedSubscriber + .create() + .consumeNextWith(e -> assertTrue(e.isStartDocument())) + .consumeNextWith(e -> assertStartElement(e, "pojo")) + .consumeNextWith(e -> assertStartElement(e, "foo")) + .consumeNextWith(e -> assertCharacters(e, "foofoo")) + .consumeNextWith(e -> assertEndElement(e, "foo")) + .consumeNextWith(e -> assertStartElement(e, "bar")) + .consumeNextWith(e -> assertCharacters(e, "barbar")) + .consumeNextWith(e -> assertEndElement(e, "bar")) + .consumeNextWith(e -> assertEndElement(e, "pojo")) + .consumeNextWith(e -> assertTrue(e.isEndDocument())) + .expectComplete() + .verify(events); } private static void assertStartElement(XMLEvent event, String expectedLocalName) { diff --git a/spring-web/src/test/java/org/springframework/http/server/reactive/FlushingIntegrationTests.java b/spring-web/src/test/java/org/springframework/http/server/reactive/FlushingIntegrationTests.java index 5a007ae7e7..e7a364f4ba 100644 --- a/spring-web/src/test/java/org/springframework/http/server/reactive/FlushingIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/http/server/reactive/FlushingIntegrationTests.java @@ -23,11 +23,11 @@ import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.BodyExtractors; -import org.springframework.tests.TestSubscriber; import org.springframework.web.client.reactive.ClientRequest; import org.springframework.web.client.reactive.WebClient; @@ -56,10 +56,10 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest .takeUntil(s -> s.endsWith("data1")) .reduce((s1, s2) -> s1 + s2); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(5)) - .assertValues("data0data1"); + ScriptedSubscriber.create() + .expectNext("data0data1") + .expectComplete() + .verify(result, Duration.ofSeconds(5L)); } @Override diff --git a/spring-web/src/test/java/org/springframework/web/client/reactive/WebClientIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/reactive/WebClientIntegrationTests.java index 8d22c7b273..e321e8c69a 100644 --- a/spring-web/src/test/java/org/springframework/web/client/reactive/WebClientIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/reactive/WebClientIntegrationTests.java @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -36,7 +37,6 @@ import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.BodyExtractors; import org.springframework.http.codec.BodyInserters; import org.springframework.http.codec.Pojo; -import org.springframework.tests.TestSubscriber; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -70,14 +70,14 @@ public class WebClientIntegrationTests { .exchange(request) .map(response -> response.headers().asHttpHeaders()); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValuesWith( + ScriptedSubscriber.create() + .consumeNextWith( httpHeaders -> { assertEquals(MediaType.TEXT_PLAIN, httpHeaders.getContentType()); assertEquals(13L, httpHeaders.getContentLength()); }) - .assertComplete(); + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -98,10 +98,11 @@ public class WebClientIntegrationTests { .exchange(request) .then(response -> response.body(toMono(String.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValues("Hello Spring!") - .assertComplete(); + ScriptedSubscriber + .create() + .expectNext("Hello Spring!") + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -125,10 +126,11 @@ public class WebClientIntegrationTests { .exchange(request) .then(response -> response.body(toMono(String.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValues(content) - .assertComplete(); + ScriptedSubscriber + .create() + .expectNext(content) + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -150,10 +152,11 @@ public class WebClientIntegrationTests { .exchange(request) .then(response -> response.body(toMono(Pojo.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValuesWith(p -> assertEquals("barbar", p.getBar())) - .assertComplete(); + ScriptedSubscriber + .create() + .consumeNextWith(p -> assertEquals("barbar", p.getBar())) + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -175,13 +178,12 @@ public class WebClientIntegrationTests { .exchange(request) .flatMap(response -> response.body(toFlux(Pojo.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValuesWith( - p -> assertThat(p.getBar(), Matchers.is("bar1")), - p -> assertThat(p.getBar(), Matchers.is("bar2"))) - .assertValueCount(2) - .assertComplete(); + ScriptedSubscriber + .create() + .consumeNextWith(p -> assertThat(p.getBar(), Matchers.is("bar1"))) + .consumeNextWith(p -> assertThat(p.getBar(), Matchers.is("bar2"))) + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -206,10 +208,11 @@ public class WebClientIntegrationTests { .exchange(request) .then(response -> response.body(BodyExtractors.toMono(Pojo.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValuesWith(p -> assertEquals("BARBAR", p.getBar())) - .assertComplete(); + ScriptedSubscriber + .create() + .consumeNextWith(p -> assertEquals("BARBAR", p.getBar())) + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -234,10 +237,11 @@ public class WebClientIntegrationTests { .exchange(request) .then(response -> response.body(toMono(String.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValues("test") - .assertComplete(); + ScriptedSubscriber + .create() + .expectNext("test") + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -256,12 +260,13 @@ public class WebClientIntegrationTests { Mono result = this.webClient .exchange(request); - TestSubscriber - .subscribe(result) - .await(Duration.ofSeconds(3)) - .assertValuesWith(response -> { + ScriptedSubscriber + .create() + .consumeNextWith(response -> { assertEquals(HttpStatus.NOT_FOUND, response.statusCode()); - }); + }) + .expectComplete() + .verify(result, Duration.ofSeconds(3)); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -287,10 +292,11 @@ public class WebClientIntegrationTests { Mono result = filteredClient.exchange(request) .then(response -> response.body(toMono(String.class))); - TestSubscriber - .subscribe(result) - .awaitAndAssertNextValues("Hello Spring!") - .assertComplete(); + ScriptedSubscriber + .create() + .expectNext("Hello Spring!") + .expectComplete() + .verify(result); RecordedRequest recordedRequest = server.takeRequest(); assertEquals(1, server.getRequestCount()); @@ -302,4 +308,4 @@ public class WebClientIntegrationTests { public void tearDown() throws Exception { this.server.shutdown(); } -} +} \ No newline at end of file diff --git a/spring-web/src/test/java/org/springframework/web/server/handler/ResponseStatusExceptionHandlerTests.java b/spring-web/src/test/java/org/springframework/web/server/handler/ResponseStatusExceptionHandlerTests.java index 6b014d775c..72e0a36fcc 100644 --- a/spring-web/src/test/java/org/springframework/web/server/handler/ResponseStatusExceptionHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/server/handler/ResponseStatusExceptionHandlerTests.java @@ -21,12 +21,12 @@ import java.time.Duration; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; +import reactor.test.subscriber.ScriptedSubscriber; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; -import org.springframework.tests.TestSubscriber; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -72,8 +72,10 @@ public class ResponseStatusExceptionHandlerTests { Throwable expected = new IllegalStateException(); Mono mono = this.handler.handle(this.exchange, expected); - TestSubscriber.subscribe(mono) - .assertErrorWith(actual -> assertSame(expected, actual)); + ScriptedSubscriber + .create() + .consumeErrorWith(actual -> assertSame(expected, actual)) + .verify(mono); } }