Skip to content

Commit bcbf495

Browse files
author
Pritham Marupaka
committed
add test to ensure supplied JSON deserializer is used when available
1 parent 7dac6ee commit bcbf495

File tree

2 files changed

+93
-4
lines changed

2 files changed

+93
-4
lines changed

dialogue-serde/src/test/java/com/palantir/conjure/java/dialogue/serde/EndpointErrorTestUtils.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@
2121
import com.palantir.dialogue.TypeMarker;
2222
import com.palantir.logsafe.Arg;
2323
import com.palantir.logsafe.Safe;
24+
import java.io.ByteArrayInputStream;
25+
import java.io.IOException;
26+
import java.io.InputStream;
27+
import java.nio.charset.StandardCharsets;
28+
import java.util.ArrayList;
2429
import java.util.HashMap;
30+
import java.util.List;
2531
import java.util.Map;
2632
import java.util.Optional;
2733
import java.util.OptionalDouble;
2834
import java.util.OptionalInt;
2935
import java.util.OptionalLong;
36+
import java.util.function.Function;
3037

3138
final class EndpointErrorTestUtils {
3239
private EndpointErrorTestUtils() {}
@@ -84,9 +91,17 @@ private static boolean shouldIncludeArgInParameters(Arg<?> arg) {
8491
public static final class TypeReturningStubEncoding implements Encoding {
8592

8693
private final String contentType;
94+
private final Function<TypeMarker<?>, Encoding.Deserializer<?>> deserializerFactory;
95+
private final Map<TypeMarker<?>, Encoding.Deserializer<?>> deserializers = new HashMap<>();
8796

8897
TypeReturningStubEncoding(String contentType) {
98+
this(contentType, typeMarker -> Encodings.json().deserializer(typeMarker));
99+
}
100+
101+
TypeReturningStubEncoding(
102+
String contentType, Function<TypeMarker<?>, Encoding.Deserializer<?>> deserializerFactory) {
89103
this.contentType = contentType;
104+
this.deserializerFactory = deserializerFactory;
90105
}
91106

92107
@Override
@@ -97,9 +112,12 @@ public <T> Encoding.Serializer<T> serializer(TypeMarker<T> _type) {
97112
}
98113

99114
@Override
115+
@SuppressWarnings("unchecked")
100116
public <T> Encoding.Deserializer<T> deserializer(TypeMarker<T> type) {
101117
return input -> {
102-
return (T) Encodings.json().deserializer(type).deserialize(input);
118+
Deserializer<T> deserializer =
119+
(Deserializer<T>) deserializers.computeIfAbsent(type, deserializerFactory);
120+
return deserializer.deserialize(input);
103121
};
104122
}
105123

@@ -117,5 +135,30 @@ public boolean supportsContentType(String input) {
117135
public String toString() {
118136
return "TypeReturningStubEncoding{" + contentType + '}';
119137
}
138+
139+
@SuppressWarnings("unchecked")
140+
public <T> Encoding.Deserializer<T> getDeserializer(TypeMarker<T> type) {
141+
return (Deserializer<T>) deserializers.get(type);
142+
}
143+
}
144+
145+
public static final class ContentRecordingJsonDeserializer<T> implements Encoding.Deserializer<T> {
146+
private final List<String> deserializedContent = new ArrayList<>();
147+
private final Encoding.Deserializer<T> delegate;
148+
149+
ContentRecordingJsonDeserializer(TypeMarker<T> type) {
150+
this.delegate = Encodings.json().deserializer(type);
151+
}
152+
153+
public List<String> getDeserializedContent() {
154+
return deserializedContent;
155+
}
156+
157+
@Override
158+
public T deserialize(InputStream input) throws IOException {
159+
String inputString = new String(input.readAllBytes(), StandardCharsets.UTF_8);
160+
deserializedContent.add(inputString);
161+
return delegate.deserialize(new ByteArrayInputStream(inputString.getBytes(StandardCharsets.UTF_8)));
162+
}
120163
}
121164
}

dialogue-serde/src/test/java/com/palantir/conjure/java/dialogue/serde/EndpointErrorsConjureBodySerDeTest.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121

2222
import com.fasterxml.jackson.annotation.JsonCreator;
2323
import com.fasterxml.jackson.annotation.JsonProperty;
24+
import com.fasterxml.jackson.core.JsonProcessingException;
2425
import com.fasterxml.jackson.databind.ObjectMapper;
2526
import com.google.common.collect.ImmutableList;
2627
import com.palantir.conjure.java.api.errors.CheckedServiceException;
2728
import com.palantir.conjure.java.api.errors.ErrorType;
2829
import com.palantir.conjure.java.api.errors.RemoteException;
2930
import com.palantir.conjure.java.api.errors.SerializableError;
3031
import com.palantir.conjure.java.dialogue.serde.EndpointErrorTestUtils.ConjureError;
32+
import com.palantir.conjure.java.dialogue.serde.EndpointErrorTestUtils.ContentRecordingJsonDeserializer;
3133
import com.palantir.conjure.java.dialogue.serde.EndpointErrorTestUtils.EndpointError;
3234
import com.palantir.conjure.java.dialogue.serde.EndpointErrorTestUtils.TypeReturningStubEncoding;
3335
import com.palantir.conjure.java.serialization.ObjectMappers;
@@ -42,11 +44,15 @@
4244
import com.palantir.logsafe.UnsafeArg;
4345
import java.io.IOException;
4446
import java.util.Arrays;
47+
import java.util.List;
4548
import java.util.Optional;
4649
import javax.annotation.Nullable;
4750
import javax.annotation.processing.Generated;
51+
import org.assertj.core.api.InstanceOfAssertFactories;
4852
import org.junit.jupiter.api.Test;
4953
import org.junit.jupiter.api.extension.ExtendWith;
54+
import org.junit.jupiter.params.ParameterizedTest;
55+
import org.junit.jupiter.params.provider.ValueSource;
5056
import org.mockito.junit.jupiter.MockitoExtension;
5157

5258
@ExtendWith(MockitoExtension.class)
@@ -103,8 +109,10 @@ private TestEndpointError(
103109
}
104110
}
105111

106-
@Test
107-
public void testDeserializeCustomError() throws IOException {
112+
// The error should be deserialized using Encodings.json(), when a JSON encoding is not provided.
113+
@ParameterizedTest
114+
@ValueSource(strings = {"application/json", "text/plain"})
115+
public void testDeserializeCustomError(String supportedContentType) throws IOException {
108116
// Given
109117
TestEndpointError errorThrownByEndpoint =
110118
new TestEndpointError("value", "unsafeValue", new ComplexArg(1, "bar"), Optional.of(2), null);
@@ -114,7 +122,7 @@ public void testDeserializeCustomError() throws IOException {
114122
TestResponse response = TestResponse.withBody(responseBody)
115123
.contentType("application/json")
116124
.code(500);
117-
BodySerDe serializers = conjureBodySerDe("application/json", "text/plain");
125+
BodySerDe serializers = conjureBodySerDe(supportedContentType);
118126
DeserializerArgs<EndpointReturnBaseType> deserializerArgs = DeserializerArgs.<EndpointReturnBaseType>builder()
119127
.baseType(new TypeMarker<>() {})
120128
.success(new TypeMarker<ExpectedReturnValue>() {})
@@ -201,6 +209,44 @@ public void testDeserializeExpectedValue() {
201209
assertThat(value).isEqualTo(new ExpectedReturnValue(expectedString));
202210
}
203211

212+
// Ensure that the supplied JSON encoding is used when available.
213+
@Test
214+
public void testDeserializeWithCustomEncoding() throws JsonProcessingException {
215+
// Given
216+
TestEndpointError errorThrownByEndpoint =
217+
new TestEndpointError("value", "unsafeValue", new ComplexArg(1, "bar"), Optional.of(2), null);
218+
String responseBody =
219+
MAPPER.writeValueAsString(ConjureError.fromCheckedServiceException(errorThrownByEndpoint));
220+
221+
TypeReturningStubEncoding stubbingEncoding =
222+
new TypeReturningStubEncoding("application/json", ContentRecordingJsonDeserializer::new);
223+
BodySerDe serializers = new ConjureBodySerDe(
224+
List.of(WeightedEncoding.of(stubbingEncoding)),
225+
Encodings.emptyContainerDeserializer(),
226+
DefaultConjureRuntime.DEFAULT_SERDE_CACHE_SPEC);
227+
TestResponse response = TestResponse.withBody(responseBody)
228+
.contentType("application/json")
229+
.code(500);
230+
231+
TypeMarker<ErrorReturnValue> errorTypeMarker = new TypeMarker<>() {};
232+
DeserializerArgs<EndpointReturnBaseType> deserializerArgs = DeserializerArgs.<EndpointReturnBaseType>builder()
233+
.baseType(new TypeMarker<>() {})
234+
.success(new TypeMarker<ExpectedReturnValue>() {})
235+
.error("Default:FailedPrecondition", errorTypeMarker)
236+
.build();
237+
238+
// When
239+
serializers.deserializer(deserializerArgs).deserialize(response);
240+
241+
// Then
242+
assertThat(stubbingEncoding.getDeserializer(errorTypeMarker))
243+
.isInstanceOfSatisfying(ContentRecordingJsonDeserializer.class, deserializer -> {
244+
assertThat(deserializer.getDeserializedContent())
245+
.asInstanceOf(InstanceOfAssertFactories.LIST)
246+
.containsExactly(responseBody);
247+
});
248+
}
249+
204250
private ConjureBodySerDe conjureBodySerDe(String... contentTypes) {
205251
return new ConjureBodySerDe(
206252
Arrays.stream(contentTypes)

0 commit comments

Comments
 (0)