Refactor AbstractEncoderTestCase
Refactor AbstractEncoderTestCase to resemble AbstractDecoderTestCase Issue: SPR-17449
This commit is contained in:
@@ -18,7 +18,6 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -28,7 +27,6 @@ import reactor.test.StepVerifier;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.AbstractLeakCheckingTestCase;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -36,193 +34,245 @@ import org.springframework.util.MimeType;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.core.io.buffer.DataBufferUtils.release;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link Encoder} unit tests. Subclasses need to implement
|
||||
* {@link #input()} and {@link #outputConsumers()}, from which {@link #encode()},
|
||||
* {@link #encodeError()} and {@link #encodeCancel()} are run.
|
||||
* {@link #canEncode()} and {@link #encode()}, possibly using the wide
|
||||
* * variety of helper methods like {@link #testEncodeAll}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.1.3
|
||||
*/
|
||||
@SuppressWarnings("ProtectedField")
|
||||
public abstract class AbstractEncoderTestCase<T, E extends Encoder<T>> extends
|
||||
AbstractLeakCheckingTestCase {
|
||||
public abstract class AbstractEncoderTestCase<E extends Encoder<?>>
|
||||
extends AbstractLeakCheckingTestCase {
|
||||
|
||||
/**
|
||||
* The encoder to test.
|
||||
*/
|
||||
protected final E encoder;
|
||||
|
||||
/**
|
||||
* The type used for
|
||||
* {@link Encoder#encode(Publisher, DataBufferFactory, ResolvableType, MimeType, Map)}.
|
||||
*/
|
||||
protected final ResolvableType elementType;
|
||||
|
||||
/**
|
||||
* The mime type used for
|
||||
* {@link Encoder#encode(Publisher, DataBufferFactory, ResolvableType, MimeType, Map)}.
|
||||
* May be {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
protected final MimeType mimeType;
|
||||
|
||||
/**
|
||||
* The hints used for
|
||||
* {@link Encoder#encode(Publisher, DataBufferFactory, ResolvableType, MimeType, Map)}.
|
||||
* May be {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
protected final Map<String, Object> hints;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@code AbstractEncoderTestCase} for the given encoder and element class.
|
||||
* @param encoder the encoder
|
||||
* @param elementClass the element class
|
||||
*/
|
||||
protected AbstractEncoderTestCase(E encoder, Class<?> elementClass) {
|
||||
this(encoder, ResolvableType.forClass(elementClass), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code AbstractEncoderTestCase} for the given parameters.
|
||||
* @param encoder the encoder
|
||||
* @param elementType the element type
|
||||
* @param mimeType the mime type. May be {@code null}.
|
||||
* @param hints the hints. May be {@code null}.
|
||||
*/
|
||||
protected AbstractEncoderTestCase(E encoder, ResolvableType elementType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
protected AbstractEncoderTestCase(E encoder) {
|
||||
|
||||
Assert.notNull(encoder, "Encoder must not be null");
|
||||
Assert.notNull(elementType, "ElementType must not be null");
|
||||
|
||||
this.encoder = encoder;
|
||||
this.elementType = elementType;
|
||||
this.mimeType = mimeType;
|
||||
this.hints = hints;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to test {@link Encoder#canEncode}.
|
||||
*/
|
||||
@Test
|
||||
public abstract void canEncode() throws Exception;
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to test {@link Encoder#encode}, possibly using
|
||||
* {@link #testEncodeAll} or other helper methods.
|
||||
*/
|
||||
@Test
|
||||
public abstract void encode() throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Helper methods that tests for a variety of encoding scenarios. This methods
|
||||
* invokes:
|
||||
* <ul>
|
||||
* <li>{@link #testEncode(Publisher, ResolvableType, Consumer, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeError(Publisher, ResolvableType, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeCancel(Publisher, ResolvableType, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeEmpty(ResolvableType, MimeType, Map)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputClass the input class
|
||||
* @param stepConsumer a consumer to {@linkplain StepVerifier verify} the output
|
||||
* @param <T> the output type
|
||||
*/
|
||||
protected <T> void testEncodeAll(Publisher<? extends T> input, Class<? extends T> inputClass,
|
||||
Consumer<StepVerifier.FirstStep<DataBuffer>> stepConsumer) {
|
||||
testEncodeAll(input, ResolvableType.forClass(inputClass), stepConsumer, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract template method that provides input for the encoder.
|
||||
* Used for {@link #encode()}, {@link #encodeError()}, and {@link #encodeCancel()}.
|
||||
* Helper methods that tests for a variety of decoding scenarios. This methods
|
||||
* invokes:
|
||||
* <ul>
|
||||
* <li>{@link #testEncode(Publisher, ResolvableType, Consumer, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeError(Publisher, ResolvableType, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeCancel(Publisher, ResolvableType, MimeType, Map)}</li>
|
||||
* <li>{@link #testEncodeEmpty(ResolvableType, MimeType, Map)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputType the input type
|
||||
* @param stepConsumer a consumer to {@linkplain StepVerifier verify} the output
|
||||
* @param mimeType the mime type to use for decoding. May be {@code null}.
|
||||
* @param hints the hints used for decoding. May be {@code null}.
|
||||
* @param <T> the output type
|
||||
*/
|
||||
protected abstract Flux<T> input();
|
||||
|
||||
/**
|
||||
* Abstract template method that verifies the output of the encoder.
|
||||
* The returned stream should contain a buffer consumer for each expected output, given
|
||||
* the {@linkplain #input()}.
|
||||
*/
|
||||
protected abstract Stream<Consumer<DataBuffer>> outputConsumers();
|
||||
|
||||
private Stream<Consumer<DataBuffer>> outputAndReleaseConsumers() {
|
||||
return outputConsumers()
|
||||
.map(consumer -> consumer.andThen(DataBufferUtils::release));
|
||||
protected <T> void testEncodeAll(Publisher<? extends T> input, ResolvableType inputType,
|
||||
Consumer<StepVerifier.FirstStep<DataBuffer>> stepConsumer,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
testEncode(input, inputType, stepConsumer, mimeType, hints);
|
||||
testEncodeError(input, inputType, mimeType, hints);
|
||||
testEncodeCancel(input, inputType, mimeType, hints);
|
||||
testEncodeEmpty(inputType, mimeType, hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a result consumer that expects the given String in UTF-8 encoding.
|
||||
* @param expected the expected string
|
||||
* Test a standard {@link Encoder#encode encode} scenario.
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputClass the input class
|
||||
* @param stepConsumer a consumer to {@linkplain StepVerifier verify} the output
|
||||
* @param <T> the output type
|
||||
*/
|
||||
protected <T> void testEncode(Publisher<? extends T> input, Class<? extends T> inputClass,
|
||||
Consumer<StepVerifier.FirstStep<DataBuffer>> stepConsumer) {
|
||||
testEncode(input, ResolvableType.forClass(inputClass), stepConsumer, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a standard {@link Encoder#encode encode} scenario.
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputType the input type
|
||||
* @param stepConsumer a consumer to {@linkplain StepVerifier verify} the output
|
||||
* @param mimeType the mime type to use for decoding. May be {@code null}.
|
||||
* @param hints the hints used for decoding. May be {@code null}.
|
||||
* @param <T> the output type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> void testEncode(Publisher<? extends T> input, ResolvableType inputType,
|
||||
Consumer<StepVerifier.FirstStep<DataBuffer>> stepConsumer,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Flux<DataBuffer> result = encoder().encode(input, this.bufferFactory, inputType,
|
||||
mimeType, hints);
|
||||
StepVerifier.FirstStep<DataBuffer> step = StepVerifier.create(result);
|
||||
stepConsumer.accept(step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a {@link Encoder#encode encode} scenario where the input stream contains an error.
|
||||
* This test method will feed the first element of the {@code input} stream to the encoder,
|
||||
* followed by an {@link InputException}.
|
||||
* The result is expected to contain one "normal" element, followed by the error.
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputType the input type
|
||||
* @param mimeType the mime type to use for decoding. May be {@code null}.
|
||||
* @param hints the hints used for decoding. May be {@code null}.
|
||||
* @see InputException
|
||||
*/
|
||||
protected void testEncodeError(Publisher<?> input, ResolvableType inputType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
input = Flux.concat(
|
||||
Flux.from(input).take(1),
|
||||
Flux.error(new InputException()));
|
||||
|
||||
Flux<DataBuffer> result = encoder().encode(input, this.bufferFactory, inputType,
|
||||
mimeType, hints);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(DataBufferUtils::release)
|
||||
.expectError(InputException.class)
|
||||
.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a {@link Encoder#encode encode} scenario where the input stream is canceled.
|
||||
* This test method will feed the first element of the {@code input} stream to the decoder,
|
||||
* followed by a cancel signal.
|
||||
* The result is expected to contain one "normal" element.
|
||||
*
|
||||
* @param input the input to be provided to the encoder
|
||||
* @param inputType the input type
|
||||
* @param mimeType the mime type to use for decoding. May be {@code null}.
|
||||
* @param hints the hints used for decoding. May be {@code null}.
|
||||
*/
|
||||
protected void testEncodeCancel(Publisher<?> input, ResolvableType inputType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Flux<DataBuffer> result = encoder().encode(input, this.bufferFactory, inputType, mimeType,
|
||||
hints);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(DataBufferUtils::release)
|
||||
.thenCancel()
|
||||
.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a {@link Encoder#encode encode} scenario where the input stream is empty.
|
||||
* The output is expected to be empty as well.
|
||||
*
|
||||
* @param inputType the input type
|
||||
* @param mimeType the mime type to use for decoding. May be {@code null}.
|
||||
* @param hints the hints used for decoding. May be {@code null}.
|
||||
*/
|
||||
protected void testEncodeEmpty(ResolvableType inputType, @Nullable MimeType mimeType,
|
||||
@Nullable Map<String, Object> hints) {
|
||||
|
||||
Flux<?> input = Flux.empty();
|
||||
Flux<DataBuffer> result = encoder().encode(input, this.bufferFactory, inputType,
|
||||
mimeType, hints);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a result consumer that expects the given bytes.
|
||||
* @param expected the expected bytes
|
||||
* @return a consumer that expects the given data buffer to be equal to {@code expected}
|
||||
*/
|
||||
protected final Consumer<DataBuffer> resultConsumer(String expected) {
|
||||
protected final Consumer<DataBuffer> expectBytes(byte[] expected) {
|
||||
return dataBuffer -> {
|
||||
byte[] resultBytes = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(resultBytes);
|
||||
release(dataBuffer);
|
||||
assertArrayEquals(expected, resultBytes);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a result consumer that expects the given string, using the UTF-8 encoding.
|
||||
* @param expected the expected string
|
||||
* @return a consumer that expects the given data buffer to be equal to {@code expected}
|
||||
*/
|
||||
protected Consumer<DataBuffer> expectString(String expected) {
|
||||
return dataBuffer -> {
|
||||
byte[] resultBytes = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(resultBytes);
|
||||
release(dataBuffer);
|
||||
String actual = new String(resultBytes, UTF_8);
|
||||
assertEquals(expected, actual);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a result consumer that expects the given bytes.
|
||||
* @param expected the expected string
|
||||
* @return a consumer that expects the given data buffer to be equal to {@code expected}
|
||||
*/
|
||||
protected final Consumer<DataBuffer> resultConsumer(byte[] expected) {
|
||||
return dataBuffer -> {
|
||||
byte[] resultBytes = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(resultBytes);
|
||||
assertArrayEquals(expected, resultBytes);
|
||||
};
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Encoder<T> encoder() {
|
||||
return (Encoder<T>) this.encoder;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether passing {@link #input()} to the encoder can be consumed with
|
||||
* {@link #outputConsumers()}.
|
||||
* Exception used in {@link #testEncodeError}.
|
||||
*/
|
||||
@Test
|
||||
public final void encode() {
|
||||
Flux<T> input = input();
|
||||
@SuppressWarnings("serial")
|
||||
public static class InputException extends RuntimeException {
|
||||
|
||||
Flux<DataBuffer> output = this.encoder.encode(input, this.bufferFactory,
|
||||
this.elementType, this.mimeType, this.hints);
|
||||
|
||||
StepVerifier.Step<DataBuffer> step = StepVerifier.create(output);
|
||||
|
||||
outputAndReleaseConsumers().forEach(step::consumeNextWith);
|
||||
|
||||
step.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether passing an error to the encoder can be consumed with
|
||||
* {@link #outputConsumers()}.
|
||||
*/
|
||||
@Test
|
||||
public final void encodeError() {
|
||||
|
||||
boolean singleValue = this.encoder instanceof AbstractSingleValueEncoder;
|
||||
|
||||
Flux<T> input;
|
||||
if (singleValue) {
|
||||
input = Flux.error(new RuntimeException());
|
||||
}
|
||||
else {
|
||||
input = Flux.concat(
|
||||
input().take(1),
|
||||
Flux.error(new RuntimeException()));
|
||||
}
|
||||
|
||||
Flux<DataBuffer> output = this.encoder.encode(input, this.bufferFactory,
|
||||
this.elementType, this.mimeType, this.hints);
|
||||
|
||||
if (singleValue) {
|
||||
StepVerifier.create(output)
|
||||
.expectError(RuntimeException.class)
|
||||
.verify();
|
||||
}
|
||||
else {
|
||||
Consumer<DataBuffer> firstResultConsumer = outputAndReleaseConsumers().findFirst()
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
StepVerifier.create(output)
|
||||
.consumeNextWith(firstResultConsumer)
|
||||
.expectError(RuntimeException.class)
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether canceling the output of the encoder can be consumed with
|
||||
* {@link #outputConsumers()}.
|
||||
*/
|
||||
@Test
|
||||
public final void encodeCancel() {
|
||||
Flux<T> input = input();
|
||||
|
||||
Flux<DataBuffer> output = this.encoder.encode(input, this.bufferFactory,
|
||||
this.elementType, this.mimeType, this.hints);
|
||||
|
||||
Consumer<DataBuffer> firstResultConsumer = outputAndReleaseConsumers().findFirst()
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
StepVerifier.create(output)
|
||||
.consumeNextWith(firstResultConsumer)
|
||||
.thenCancel()
|
||||
.verify();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,14 +17,11 @@
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -32,30 +29,18 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ByteArrayEncoderTests extends AbstractEncoderTestCase<byte[], ByteArrayEncoder> {
|
||||
public class ByteArrayEncoderTests extends AbstractEncoderTestCase<ByteArrayEncoder> {
|
||||
|
||||
private final byte[] fooBytes = "foo".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final byte[] barBytes = "bar".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
public ByteArrayEncoderTests() {
|
||||
super(new ByteArrayEncoder(), byte[].class);
|
||||
super(new ByteArrayEncoder());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Flux<byte[]> input() {
|
||||
return Flux.just(this.fooBytes,
|
||||
this.barBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Consumer<DataBuffer>> outputConsumers() {
|
||||
return Stream.<Consumer<DataBuffer>>builder()
|
||||
.add(resultConsumer(this.fooBytes))
|
||||
.add(resultConsumer(this.barBytes))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canEncode() {
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(byte[].class),
|
||||
@@ -69,4 +54,13 @@ public class ByteArrayEncoderTests extends AbstractEncoderTestCase<byte[], ByteA
|
||||
assertFalse(this.encoder.canEncode(ResolvableType.NONE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode() {
|
||||
Flux<byte[]> input = Flux.just(this.fooBytes, this.barBytes);
|
||||
|
||||
testEncodeAll(input, byte[].class, step -> step
|
||||
.consumeNextWith(expectBytes(this.fooBytes))
|
||||
.consumeNextWith(expectBytes(this.barBytes))
|
||||
.verifyComplete());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,11 @@ package org.springframework.core.codec;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -33,30 +30,17 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class ByteBufferEncoderTests extends AbstractEncoderTestCase<ByteBuffer, ByteBufferEncoder> {
|
||||
public class ByteBufferEncoderTests extends AbstractEncoderTestCase<ByteBufferEncoder> {
|
||||
|
||||
private final byte[] fooBytes = "foo".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final byte[] barBytes = "bar".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
public ByteBufferEncoderTests() {
|
||||
super(new ByteBufferEncoder(), ByteBuffer.class);
|
||||
super(new ByteBufferEncoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Flux<ByteBuffer> input() {
|
||||
return Flux.just(this.fooBytes, this.barBytes)
|
||||
.map(ByteBuffer::wrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Consumer<DataBuffer>> outputConsumers() {
|
||||
return Stream.<Consumer<DataBuffer>>builder()
|
||||
.add(resultConsumer(this.fooBytes))
|
||||
.add(resultConsumer(this.barBytes))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canEncode() {
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(ByteBuffer.class),
|
||||
@@ -70,5 +54,17 @@ public class ByteBufferEncoderTests extends AbstractEncoderTestCase<ByteBuffer,
|
||||
assertFalse(this.encoder.canEncode(ResolvableType.NONE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void encode() {
|
||||
Flux<ByteBuffer> input = Flux.just(this.fooBytes, this.barBytes)
|
||||
.map(ByteBuffer::wrap);
|
||||
|
||||
testEncodeAll(input, ByteBuffer.class, step -> step
|
||||
.consumeNextWith(expectBytes(this.fooBytes))
|
||||
.consumeNextWith(expectBytes(this.barBytes))
|
||||
.verifyComplete());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,9 @@
|
||||
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -32,31 +27,19 @@ import static org.junit.Assert.*;
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class CharSequenceEncoderTests
|
||||
extends AbstractEncoderTestCase<CharSequence, CharSequenceEncoder> {
|
||||
extends AbstractEncoderTestCase<CharSequenceEncoder> {
|
||||
|
||||
private final String foo = "foo";
|
||||
|
||||
private final String bar = "bar";
|
||||
|
||||
public CharSequenceEncoderTests() {
|
||||
super(CharSequenceEncoder.textPlainOnly(), CharSequence.class);
|
||||
super(CharSequenceEncoder.textPlainOnly());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Flux<CharSequence> input() {
|
||||
return Flux.just(this.foo, this.bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Consumer<DataBuffer>> outputConsumers() {
|
||||
return Stream.<Consumer<DataBuffer>>builder()
|
||||
.add(resultConsumer(this.foo))
|
||||
.add(resultConsumer(this.bar))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canWrite() {
|
||||
public void canEncode() throws Exception {
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(String.class),
|
||||
MimeTypeUtils.TEXT_PLAIN));
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(StringBuilder.class),
|
||||
@@ -71,4 +54,17 @@ public class CharSequenceEncoderTests
|
||||
// SPR-15464
|
||||
assertFalse(this.encoder.canEncode(ResolvableType.NONE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode() {
|
||||
Flux<CharSequence> input = Flux.just(this.foo, this.bar);
|
||||
|
||||
testEncodeAll(input, CharSequence.class, step -> step
|
||||
.consumeNextWith(expectString(this.foo))
|
||||
.consumeNextWith(expectString(this.bar))
|
||||
.verifyComplete());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
@@ -32,36 +31,18 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class DataBufferEncoderTests extends AbstractEncoderTestCase<DataBuffer, DataBufferEncoder> {
|
||||
public class DataBufferEncoderTests extends AbstractEncoderTestCase<DataBufferEncoder> {
|
||||
|
||||
private final byte[] fooBytes = "foo".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final byte[] barBytes = "bar".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
public DataBufferEncoderTests() {
|
||||
super(new DataBufferEncoder(), DataBuffer.class);
|
||||
super(new DataBufferEncoder());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Flux<DataBuffer> input() {
|
||||
// DefaultDataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
return Flux.just(this.fooBytes, this.barBytes)
|
||||
.map(bytes -> {
|
||||
DataBuffer dataBuffer = bufferFactory.allocateBuffer(bytes.length);
|
||||
dataBuffer.write(bytes);
|
||||
return dataBuffer;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Consumer<DataBuffer>> outputConsumers() {
|
||||
return Stream.<Consumer<DataBuffer>>builder()
|
||||
.add(resultConsumer(this.fooBytes))
|
||||
.add(resultConsumer(this.barBytes))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canEncode() {
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(DataBuffer.class),
|
||||
@@ -75,4 +56,21 @@ public class DataBufferEncoderTests extends AbstractEncoderTestCase<DataBuffer,
|
||||
assertFalse(this.encoder.canEncode(ResolvableType.NONE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode() throws Exception {
|
||||
Flux<DataBuffer> input = Flux.just(this.fooBytes, this.barBytes)
|
||||
.flatMap(bytes -> Mono.defer(() -> {
|
||||
DataBuffer dataBuffer = this.bufferFactory.allocateBuffer(bytes.length);
|
||||
dataBuffer.write(bytes);
|
||||
return Mono.just(dataBuffer);
|
||||
}));
|
||||
|
||||
testEncodeAll(input, DataBuffer.class, step -> step
|
||||
.consumeNextWith(expectBytes(this.fooBytes))
|
||||
.consumeNextWith(expectBytes(this.barBytes))
|
||||
.verifyComplete());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,20 @@
|
||||
|
||||
package org.springframework.core.codec;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -35,27 +38,16 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ResourceEncoderTests extends AbstractEncoderTestCase<Resource, ResourceEncoder> {
|
||||
public class ResourceEncoderTests extends AbstractEncoderTestCase<ResourceEncoder> {
|
||||
|
||||
private final byte[] bytes = "foo".getBytes(UTF_8);
|
||||
|
||||
|
||||
public ResourceEncoderTests() {
|
||||
super(new ResourceEncoder(), Resource.class);
|
||||
super(new ResourceEncoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Flux<Resource> input() {
|
||||
return Flux.just(new ByteArrayResource(this.bytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Consumer<DataBuffer>> outputConsumers() {
|
||||
return Stream.<Consumer<DataBuffer>>builder()
|
||||
.add(resultConsumer(this.bytes))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void canEncode() {
|
||||
assertTrue(this.encoder.canEncode(ResolvableType.forClass(InputStreamResource.class),
|
||||
@@ -71,4 +63,28 @@ public class ResourceEncoderTests extends AbstractEncoderTestCase<Resource, Reso
|
||||
assertFalse(this.encoder.canEncode(ResolvableType.NONE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode() {
|
||||
Flux<Resource> input = Flux.just(new ByteArrayResource(this.bytes));
|
||||
|
||||
testEncodeAll(input, Resource.class, step -> step
|
||||
.consumeNextWith(expectBytes(this.bytes))
|
||||
.verifyComplete());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testEncodeError(Publisher<?> input, ResolvableType outputType,
|
||||
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
|
||||
|
||||
Flux<Resource> i = Flux.error(new InputException());
|
||||
|
||||
Flux<DataBuffer> result = ((Encoder<Resource>) this.encoder).encode(i,
|
||||
this.bufferFactory, outputType,
|
||||
mimeType, hints);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.expectError(InputException.class)
|
||||
.verify();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user