Minor refactoring in HTTP handler tests

Change WebFlux handler to actually decode from JSON rather
than take an already decoded SerializableGraphQlRequest.

See gh-948
This commit is contained in:
rstoyanchev
2024-04-19 16:18:48 +01:00
parent 8eb3cfd19d
commit bf9c584919
2 changed files with 96 additions and 83 deletions

View File

@@ -23,22 +23,24 @@ import java.util.Locale;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
import reactor.test.StepVerifier;
import org.springframework.graphql.GraphQlRequest;
import org.springframework.graphql.GraphQlSetup;
import org.springframework.graphql.server.support.SerializableGraphQlRequest;
import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
@@ -48,95 +50,100 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class GraphQlHttpHandlerTests {
private final GraphQlHttpHandler greetingHandler = GraphQlSetup.schemaContent("type Query { greeting: String }")
.queryFetcher("greeting", (env) -> "Hello").toHttpHandlerWebFlux();
private static final List<HttpMessageReader<?>> MESSAGE_READERS =
List.of(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
private final GraphQlHttpHandler greetingHandler =
GraphQlSetup.schemaContent("type Query { greeting: String }")
.queryFetcher("greeting", (env) -> "Hello")
.toHttpHandlerWebFlux();
@Test
void shouldProduceApplicationJsonByDefault() {
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.ALL).build();
void shouldProduceApplicationJsonByDefault() throws Exception {
String document = "{greeting}";
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, this.greetingHandler, initRequest(document));
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.ALL)
.body(initRequestBody(document));
assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
MockServerHttpResponse response = handleRequest(httpRequest, this.greetingHandler);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
StepVerifier.create(response.getBodyAsString())
.expectNext("{\"data\":{\"greeting\":\"Hello\"}}")
.verifyComplete();
}
@Test
void shouldProduceApplicationGraphQl() {
void shouldProduceApplicationGraphQl() throws Exception {
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_GRAPHQL_RESPONSE).build();
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_GRAPHQL_RESPONSE)
.body(initRequestBody("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, this.greetingHandler, initRequest("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(httpRequest, this.greetingHandler);
assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_GRAPHQL_RESPONSE);
}
@Test
void shouldProduceApplicationJson() {
void shouldProduceApplicationJson() throws Exception {
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).build();
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(initRequestBody("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, this.greetingHandler, initRequest("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(httpRequest, this.greetingHandler);
assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
}
@Test
void locale() {
void locale() throws Exception {
GraphQlHttpHandler handler = GraphQlSetup.schemaContent("type Query { greeting: String }")
.queryFetcher("greeting", (env) -> "Hello in " + env.getLocale())
.toHttpHandlerWebFlux();
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_GRAPHQL_RESPONSE)
.acceptLanguageAsLocales(Locale.FRENCH).build();
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_GRAPHQL_RESPONSE)
.acceptLanguageAsLocales(Locale.FRENCH)
.body(initRequestBody("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, handler, initRequest("{greeting}"));
MockServerHttpResponse httpResponse = handleRequest(httpRequest, handler);
assertThat(httpResponse.getBodyAsString().block())
.isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}");
}
@Test
void shouldSetExecutionId() {
void shouldSetExecutionId() throws Exception {
GraphQlHttpHandler handler = GraphQlSetup.schemaContent("type Query { showId: String }")
.queryFetcher("showId", (env) -> env.getExecutionId().toString())
.toHttpHandlerWebFlux();
MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_GRAPHQL_RESPONSE).build();
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_GRAPHQL_RESPONSE)
.body(initRequestBody("{showId}"));
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, handler, initRequest("{showId}"));
MockServerHttpResponse httpResponse = handleRequest(httpRequest, handler);
DocumentContext document = JsonPath.parse(httpResponse.getBodyAsString().block());
String id = document.read("data.showId", String.class);
assertThat(id).isEqualTo(httpRequest.getId());
}
private static SerializableGraphQlRequest initRequest(String document) {
private static String initRequestBody(String document) throws Exception {
SerializableGraphQlRequest request = new SerializableGraphQlRequest();
request.setQuery(document);
return request;
return new ObjectMapper().writeValueAsString(request);
}
private MockServerHttpResponse handleRequest(
MockServerHttpRequest httpRequest, GraphQlHttpHandler handler, GraphQlRequest body) {
private MockServerHttpResponse handleRequest(MockServerHttpRequest httpRequest, GraphQlHttpHandler handler) {
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
MockServerRequest serverRequest = MockServerRequest.builder()
.exchange(exchange)
.uri(((ServerWebExchange) exchange).getRequest().getURI())
.method(((ServerWebExchange) exchange).getRequest().getMethod())
.headers(((ServerWebExchange) exchange).getRequest().getHeaders())
.body(Mono.just(body));
ServerRequest serverRequest = ServerRequest.create(exchange, MESSAGE_READERS);
handler.handleRequest(serverRequest)
.flatMap(response -> response.writeTo(exchange, new DefaultContext()))

View File

@@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import com.jayway.jsonpath.DocumentContext;
@@ -29,9 +30,11 @@ import graphql.execution.preparsed.persisted.ApolloPersistedQuerySupport;
import graphql.execution.preparsed.persisted.InMemoryPersistedQueryCache;
import jakarta.servlet.ServletException;
import org.junit.jupiter.api.Test;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.graphql.GraphQlSetup;
import org.springframework.graphql.server.support.SerializableGraphQlRequest;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@@ -57,23 +60,24 @@ public class GraphQlHttpHandlerTests {
private final GraphQlHttpHandler greetingHandler = GraphQlSetup.schemaContent("type Query { greeting: String }")
.queryFetcher("greeting", (env) -> "Hello").toHttpHandler();
@Test
void shouldProduceApplicationJsonByDefault() throws Exception {
MockHttpServletRequest servletRequest = createServletRequest("{\"query\":\"{ greeting }\"}", "*/*");
MockHttpServletResponse servletResponse = handleRequest(servletRequest, this.greetingHandler);
assertThat(servletResponse.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
MockHttpServletRequest request = createServletRequest("{ greeting }", "*/*");
MockHttpServletResponse response = handleRequest(request, this.greetingHandler);
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
void shouldProduceApplicationGraphQl() throws Exception {
MockHttpServletRequest servletRequest = createServletRequest("{\"query\":\"{ greeting }\"}", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletResponse servletResponse = handleRequest(servletRequest, this.greetingHandler);
assertThat(servletResponse.getContentType()).isEqualTo(MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletRequest request = createServletRequest("{ greeting }", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletResponse response = handleRequest(request, this.greetingHandler);
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
}
@Test
void shouldProduceApplicationJson() throws Exception {
MockHttpServletRequest servletRequest = createServletRequest("{\"query\":\"{ greeting }\"}", "application/json");
MockHttpServletRequest servletRequest = createServletRequest("{ greeting }", "application/json");
MockHttpServletResponse servletResponse = handleRequest(servletRequest, this.greetingHandler);
assertThat(servletResponse.getContentType()).isEqualTo("application/json");
}
@@ -83,14 +87,15 @@ public class GraphQlHttpHandlerTests {
GraphQlHttpHandler handler = GraphQlSetup.schemaContent("type Query { greeting: String }")
.queryFetcher("greeting", (env) -> "Hello in " + env.getLocale())
.toHttpHandler();
MockHttpServletRequest servletRequest = createServletRequest("{\"query\":\"{ greeting }\"}", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletRequest request = createServletRequest(
"{ greeting }", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
LocaleContextHolder.setLocale(Locale.FRENCH);
try {
MockHttpServletResponse servletResponse = handleRequest(servletRequest, handler);
assertThat(servletResponse.getContentAsString())
.isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}");
MockHttpServletResponse response = handleRequest(request, handler);
assertThat(response.getContentAsString()).isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}");
}
finally {
LocaleContextHolder.resetLocaleContext();
@@ -103,10 +108,12 @@ public class GraphQlHttpHandlerTests {
.queryFetcher("showId", (env) -> env.getExecutionId().toString())
.toHttpHandler();
MockHttpServletRequest servletRequest = createServletRequest("{\"query\":\"{ showId }\"}", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletRequest request = createServletRequest(
"{ showId }", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);
MockHttpServletResponse servletResponse = handleRequest(servletRequest, handler);
DocumentContext document = JsonPath.parse(servletResponse.getContentAsString());
MockHttpServletResponse response = handleRequest(request, handler);
DocumentContext document = JsonPath.parse(response.getContentAsString());
String id = document.read("data.showId", String.class);
assertThatNoException().isThrownBy(() -> UUID.fromString(id));
}
@@ -121,44 +128,44 @@ public class GraphQlHttpHandlerTests {
.configureGraphQl(builder -> builder.preparsedDocumentProvider(documentProvider))
.toHttpHandler();
String document = """
{
"query" : "{__typename}",
"extensions": {
"persistedQuery": {
"version":1,
"sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38"
}
}
}""";
SerializableGraphQlRequest request = new SerializableGraphQlRequest();
request.setQuery("{__typename}");
request.setExtensions(Map.of("persistedQuery", Map.of(
"version", "1",
"sha256Hash", "ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38")));
MockHttpServletResponse servletResponse = handleRequest(createServletRequest(document, "*/*"), handler);
assertThat(servletResponse.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}");
MockHttpServletResponse response = handleRequest(createServletRequest(request, "*/*"), handler);
assertThat(response.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}");
document = """
{
"extensions":{
"persistedQuery":{
"version":1,
"sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38"
}
}
}""";
request = new SerializableGraphQlRequest();
request.setQuery("{__typename}");
request.setExtensions(Map.of("persistedQuery", Map.of(
"version", "1",
"sha256Hash", "ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38")));
servletResponse = handleRequest(createServletRequest(document, "*/*"), handler);
assertThat(servletResponse.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}");
response = handleRequest(createServletRequest(request, "*/*"), handler);
assertThat(response.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}");
}
private MockHttpServletRequest createServletRequest(String document, String accept) throws Exception {
SerializableGraphQlRequest request = new SerializableGraphQlRequest();
request.setQuery(document);
return createServletRequest(request, accept);
}
private MockHttpServletRequest createServletRequest(String query, String accept) {
private MockHttpServletRequest createServletRequest(SerializableGraphQlRequest request, String accept) throws Exception {
MockHttpServletRequest servletRequest = new MockHttpServletRequest("POST", "/");
servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);
servletRequest.setContent(query.getBytes(StandardCharsets.UTF_8));
servletRequest.setContent(initRequestBody(request));
servletRequest.addHeader("Accept", accept);
servletRequest.setAsyncSupported(true);
return servletRequest;
}
private static byte[] initRequestBody(SerializableGraphQlRequest request) throws Exception {
return new ObjectMapper().writeValueAsString(request).getBytes(StandardCharsets.UTF_8);
}
private MockHttpServletResponse handleRequest(
MockHttpServletRequest servletRequest, GraphQlHttpHandler handler) throws ServletException, IOException {
@@ -180,7 +187,6 @@ public class GraphQlHttpHandlerTests {
public List<HttpMessageConverter<?>> messageConverters() {
return MESSAGE_READERS;
}
}
}