Refactoring in spring-graphql tests
Change GraphQlTestUtils to match how tests have evolved with regards to how GraphQlSource is initialized and ensure all tests use it.
This commit is contained in:
@@ -24,8 +24,14 @@ import java.util.stream.Collectors;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
public class BookSource {
|
||||
|
||||
public static final Resource schema = new ClassPathResource("books/schema.graphqls");
|
||||
|
||||
|
||||
private static final Map<Long, Book> booksMap = new HashMap<>();
|
||||
|
||||
private static final Map<Long, Book> booksWithoutAuthorsMap;
|
||||
|
||||
@@ -17,16 +17,15 @@
|
||||
package org.springframework.graphql;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import graphql.ExecutionResult;
|
||||
import graphql.GraphQL;
|
||||
import graphql.schema.DataFetcher;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -36,39 +35,49 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public abstract class GraphQlTestUtils {
|
||||
|
||||
public static GraphQL initGraphQl(
|
||||
String schemaContent, String typeName, String fieldName, DataFetcher<?> fetcher) {
|
||||
/**
|
||||
* Convenience method for a {@link GraphQlSource.Builder} with a single {@link DataFetcher}.
|
||||
*
|
||||
* @param schema either String content or a {@link Resource}.
|
||||
* @param typeName the parent type name (Query, Mutation, or Subscription).
|
||||
* @param fieldName the name of the operation
|
||||
* @param fetcher the fetcher to use
|
||||
*
|
||||
* @return the created builder
|
||||
*/
|
||||
public static GraphQlSource.Builder graphQlSource(
|
||||
Object schema, String typeName, String fieldName, DataFetcher<?> fetcher) {
|
||||
|
||||
return initGraphQlSource(schemaContent, typeName, fieldName, fetcher)
|
||||
.build()
|
||||
.graphQl();
|
||||
return graphQlSource(schema,
|
||||
wiring -> wiring.type(typeName, builder -> builder.dataFetcher(fieldName, fetcher)));
|
||||
}
|
||||
|
||||
public static GraphQL initGraphQl(
|
||||
String schemaContent, String typeName, String fieldName, DataFetcher<?> fetcher,
|
||||
DataFetcherExceptionResolver... resolvers) {
|
||||
|
||||
return initGraphQlSource(schemaContent, typeName, fieldName, fetcher)
|
||||
.exceptionResolvers(Arrays.asList(resolvers))
|
||||
.build()
|
||||
.graphQl();
|
||||
}
|
||||
|
||||
public static GraphQlSource.Builder initGraphQlSource(
|
||||
String schemaContent, String typeName, String fieldName, DataFetcher<?> fetcher) {
|
||||
/**
|
||||
* Convenience method for a {@link GraphQlSource.Builder} when multiple
|
||||
* {@link DataFetcher} registrations might be needed.
|
||||
*
|
||||
* @param schema either String content or a {@link Resource}.
|
||||
* @param configurer the configurer to apply to the RuntimeWiring
|
||||
*
|
||||
* @return the created builder
|
||||
*/
|
||||
public static GraphQlSource.Builder graphQlSource(Object schema, RuntimeWiringConfigurer configurer) {
|
||||
Resource schemaResource = (schema instanceof String ?
|
||||
new ByteArrayResource(((String) schema).getBytes(StandardCharsets.UTF_8)) :
|
||||
(Resource) schema);
|
||||
|
||||
return GraphQlSource.builder()
|
||||
.schemaResources(new ByteArrayResource(schemaContent.getBytes(StandardCharsets.UTF_8)))
|
||||
.configureRuntimeWiring(wiring -> wiring.type(typeName, (builder) -> builder.dataFetcher(fieldName, fetcher)));
|
||||
.schemaResources(schemaResource)
|
||||
.configureRuntimeWiring(configurer);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T checkErrorsAndGetData(@Nullable ExecutionResult result, String key) {
|
||||
Map<String, Object> map = checkErrorsAndGetData(result);
|
||||
public static <T> T getData(@Nullable ExecutionResult result, String key) {
|
||||
Map<String, Object> map = getData(result);
|
||||
return (T) map.get(key);
|
||||
}
|
||||
|
||||
public static <T> T checkErrorsAndGetData(@Nullable ExecutionResult result) {
|
||||
public static <T> T getData(@Nullable ExecutionResult result) {
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getErrors()).as("Errors present in GraphQL response").isEmpty();
|
||||
T data = result.getData();
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.graphql;
|
||||
|
||||
import graphql.GraphQL;
|
||||
import graphql.schema.GraphQLSchema;
|
||||
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
|
||||
/**
|
||||
* {@link GraphQlSource} that wraps a pre-built {@link GraphQL} instance.
|
||||
*/
|
||||
public class TestGraphQlSource implements GraphQlSource {
|
||||
|
||||
private final GraphQL graphQl;
|
||||
|
||||
public TestGraphQlSource(GraphQL graphQl) {
|
||||
this.graphQl = graphQl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphQL graphQl() {
|
||||
return this.graphQl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphQLSchema schema() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.data.method.annotation.Argument;
|
||||
import org.springframework.graphql.data.method.annotation.MutationMapping;
|
||||
@@ -43,7 +42,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ArgumentMethodArgumentResolver}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class ArgumentMethodArgumentResolverTests {
|
||||
@@ -55,24 +53,25 @@ class ArgumentMethodArgumentResolverTests {
|
||||
@Test
|
||||
void shouldSupportAnnotatedParameters() {
|
||||
Method bookById = ClassUtils.getMethod(BookController.class, "bookById", Long.class);
|
||||
MethodParameter methodParameter = getMethodParameter(bookById, 0);
|
||||
MethodParameter methodParameter = methodParam(bookById, 0);
|
||||
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotSupportParametersWithoutAnnotation() {
|
||||
Method notSupported = ClassUtils.getMethod(BookController.class, "notSupported", String.class);
|
||||
MethodParameter methodParameter = getMethodParameter(notSupported, 0);
|
||||
MethodParameter methodParameter = methodParam(notSupported, 0);
|
||||
|
||||
assertThat(resolver.supportsParameter(methodParameter)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveBasicTypeArgument() throws Exception {
|
||||
Method bookById = ClassUtils.getMethod(BookController.class, "bookById", Long.class);
|
||||
String payload = "{\"id\": 42 }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
MethodParameter methodParameter = getMethodParameter(bookById, 0);
|
||||
Object result = resolver.resolveArgument(methodParameter, environment);
|
||||
DataFetchingEnvironment environment = initEnvironment("{\"id\": 42 }");
|
||||
Object result = resolver.resolveArgument(methodParam(bookById, 0), environment);
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(Long.class).isEqualTo(42L);
|
||||
}
|
||||
|
||||
@@ -81,8 +80,8 @@ class ArgumentMethodArgumentResolverTests {
|
||||
Method addBook = ClassUtils.getMethod(BookController.class, "addBook", BookInput.class);
|
||||
String payload = "{\"bookInput\": { \"name\": \"test name\", \"authorId\": 42} }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
MethodParameter methodParameter = getMethodParameter(addBook, 0);
|
||||
Object result = resolver.resolveArgument(methodParameter, environment);
|
||||
Object result = resolver.resolveArgument(methodParam(addBook, 0), environment);
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(BookInput.class);
|
||||
assertThat((BookInput) result).hasFieldOrPropertyWithValue("name", "test name")
|
||||
.hasFieldOrPropertyWithValue("authorId", 42L);
|
||||
@@ -93,8 +92,8 @@ class ArgumentMethodArgumentResolverTests {
|
||||
Method addBooks = ClassUtils.getMethod(BookController.class, "addBooks", List.class);
|
||||
String payload = "{\"books\": [{ \"name\": \"first\", \"authorId\": 42}, { \"name\": \"second\", \"authorId\": 24}] }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
MethodParameter methodParameter = getMethodParameter(addBooks, 0);
|
||||
Object result = resolver.resolveArgument(methodParameter, environment);
|
||||
Object result = resolver.resolveArgument(methodParam(addBooks, 0), environment);
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(List.class);
|
||||
assertThat(result).asList().allMatch(item -> item instanceof Book)
|
||||
.extracting("name").containsExactly("first", "second");
|
||||
@@ -105,13 +104,13 @@ class ArgumentMethodArgumentResolverTests {
|
||||
Method bookByKeyword = ClassUtils.getMethod(BookController.class, "bookByKeyword", Keyword.class);
|
||||
String payload = "{\"keyword\": \"test\" }";
|
||||
DataFetchingEnvironment environment = initEnvironment(payload);
|
||||
MethodParameter methodParameter = getMethodParameter(bookByKeyword, 0);
|
||||
Object result = resolver.resolveArgument(methodParameter, environment);
|
||||
Object result = resolver.resolveArgument(methodParam(bookByKeyword, 0), environment);
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(Keyword.class);
|
||||
assertThat((Keyword) result).hasFieldOrPropertyWithValue("term", "test");
|
||||
}
|
||||
|
||||
private MethodParameter getMethodParameter(Method method, int index) {
|
||||
private MethodParameter methodParam(Method method, int index) {
|
||||
MethodParameter methodParameter = new MethodParameter(method, index);
|
||||
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
|
||||
return methodParameter;
|
||||
@@ -122,6 +121,7 @@ class ArgumentMethodArgumentResolverTests {
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(arguments).build();
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
static class BookController {
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -36,7 +35,6 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.RequestInput;
|
||||
@@ -121,7 +119,7 @@ public class BatchMappingInvocationTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
List<Map<String, Object>> actualCourses = GraphQlTestUtils.checkErrorsAndGetData(result, "courses");
|
||||
List<Map<String, Object>> actualCourses = GraphQlTestUtils.getData(result, "courses");
|
||||
List<Course> courses = Course.allCourses();
|
||||
assertThat(actualCourses).hasSize(courses.size());
|
||||
|
||||
@@ -153,7 +151,7 @@ public class BatchMappingInvocationTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
List<Map<String, Object>> actualCourses = GraphQlTestUtils.checkErrorsAndGetData(result, "courses");
|
||||
List<Map<String, Object>> actualCourses = GraphQlTestUtils.getData(result, "courses");
|
||||
|
||||
List<Course> courses = Course.allCourses();
|
||||
assertThat(actualCourses).hasSize(courses.size());
|
||||
@@ -253,15 +251,8 @@ public class BatchMappingInvocationTests {
|
||||
private static class CourseConfig {
|
||||
|
||||
@Bean
|
||||
public GraphQlSource graphQlSource(AnnotatedControllerConfigurer configurer) {
|
||||
return GraphQlSource.builder()
|
||||
.schemaResources(new ByteArrayResource(schema.getBytes(StandardCharsets.UTF_8)))
|
||||
.configureRuntimeWiring(configurer)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GraphQlService graphQlService(GraphQlSource source, BatchLoaderRegistry registry) {
|
||||
public GraphQlService graphQlService(AnnotatedControllerConfigurer configurer, BatchLoaderRegistry registry) {
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(schema, configurer).build();
|
||||
ExecutionGraphQlService service = new ExecutionGraphQlService(source);
|
||||
service.addDataLoaderRegistrar(registry);
|
||||
return service;
|
||||
|
||||
@@ -57,8 +57,7 @@ public class DataFetchingEnvironmentArgumentResolverTests {
|
||||
@Test
|
||||
void resolveGraphQlContext() {
|
||||
GraphQLContext context = GraphQLContext.newContext().build();
|
||||
DataFetchingEnvironment environment =
|
||||
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().graphQLContext(context).build();
|
||||
DataFetchingEnvironment environment = environment().graphQLContext(context).build();
|
||||
Object actual = this.resolver.resolveArgument(parameter(0), environment);
|
||||
|
||||
assertThat(actual).isSameAs(context);
|
||||
@@ -67,8 +66,7 @@ public class DataFetchingEnvironmentArgumentResolverTests {
|
||||
@Test
|
||||
void resolveSelectionSet() {
|
||||
DataFetchingFieldSelectionSet selectionSet = mock(DataFetchingFieldSelectionSet.class);
|
||||
DataFetchingEnvironment environment =
|
||||
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().selectionSet(selectionSet).build();
|
||||
DataFetchingEnvironment environment = environment().selectionSet(selectionSet).build();
|
||||
Object actual = this.resolver.resolveArgument(parameter(1), environment);
|
||||
|
||||
assertThat(actual).isSameAs(selectionSet);
|
||||
@@ -77,18 +75,17 @@ public class DataFetchingEnvironmentArgumentResolverTests {
|
||||
@Test
|
||||
void resolveLocale() {
|
||||
Locale locale = Locale.ITALIAN;
|
||||
DataFetchingEnvironment environment =
|
||||
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().locale(locale).build();
|
||||
DataFetchingEnvironment environment = environment().locale(locale).build();
|
||||
Object actual = this.resolver.resolveArgument(parameter(2), environment);
|
||||
|
||||
assertThat(actual).isSameAs(locale);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void resolveOptionalLocale() {
|
||||
Locale locale = Locale.ITALIAN;
|
||||
DataFetchingEnvironment environment =
|
||||
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().locale(locale).build();
|
||||
DataFetchingEnvironment environment = environment().locale(locale).build();
|
||||
Optional<Locale> actual = (Optional<Locale>) this.resolver.resolveArgument(parameter(3), environment);
|
||||
|
||||
assertThat(actual).isNotNull();
|
||||
@@ -96,14 +93,22 @@ public class DataFetchingEnvironmentArgumentResolverTests {
|
||||
assertThat(actual.get()).isSameAs(locale);
|
||||
}
|
||||
|
||||
private static DataFetchingEnvironmentImpl.Builder environment() {
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment();
|
||||
}
|
||||
|
||||
private MethodParameter parameter(int index) {
|
||||
return new MethodParameter(handleMethod, index);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public void handle(GraphQLContext graphQLContext, DataFetchingFieldSelectionSet selectionSet,
|
||||
Locale locale, Optional<Locale> optionalLocale, String s) {
|
||||
@SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "unused"})
|
||||
public void handle(
|
||||
GraphQLContext graphQLContext,
|
||||
DataFetchingFieldSelectionSet selectionSet,
|
||||
Locale locale,
|
||||
Optional<Locale> optionalLocale,
|
||||
String s) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
@@ -38,7 +37,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DataLoaderMethodArgumentResolver}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class DataLoaderArgumentResolverTests {
|
||||
@@ -48,6 +46,8 @@ public class DataLoaderArgumentResolverTests {
|
||||
|
||||
private final DataLoaderMethodArgumentResolver resolver = new DataLoaderMethodArgumentResolver();
|
||||
|
||||
private final BatchLoaderRegistry registry = new DefaultBatchLoaderRegistry();
|
||||
|
||||
|
||||
@Test
|
||||
void supportsParameter() {
|
||||
@@ -57,70 +57,60 @@ public class DataLoaderArgumentResolverTests {
|
||||
|
||||
@Test
|
||||
void resolveArgument() {
|
||||
this.registry.forTypePair(Long.class, Author.class).registerBatchLoader((ids, env) -> Flux.empty());
|
||||
|
||||
DataFetchingEnvironment environment = initEnvironment(registry ->
|
||||
registry.forTypePair(Long.class, Author.class).registerBatchLoader((ids, env) -> Flux.empty()));
|
||||
|
||||
Object argument = this.resolver.resolveArgument(initParameter(0), environment);
|
||||
Object argument = this.resolver.resolveArgument(initParameter(0), environment());
|
||||
assertThat(argument).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveArgumentViaParameterName() {
|
||||
DataFetchingEnvironment environment = initEnvironment(registry ->
|
||||
registry.forName("namedDataLoader").registerBatchLoader((ids, env) -> Flux.empty()));
|
||||
this.registry.forName("namedDataLoader").registerBatchLoader((ids, env) -> Flux.empty());
|
||||
|
||||
MethodParameter parameter = initParameter(1);
|
||||
parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
|
||||
|
||||
Object argument = this.resolver.resolveArgument(parameter, environment);
|
||||
Object argument = this.resolver.resolveArgument(parameter, environment());
|
||||
assertThat(argument).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveArgumentFailureWithoutGenericType() {
|
||||
DataFetchingEnvironment environment = initEnvironment(registry ->
|
||||
registry.forTypePair(Long.class, Author.class).registerBatchLoader((ids, env) -> Flux.empty()));
|
||||
this.registry.forTypePair(Long.class, Author.class).registerBatchLoader((ids, env) -> Flux.empty());
|
||||
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(initParameter(2), environment))
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(initParameter(2), environment()))
|
||||
.hasMessageContaining("declaring the DataLoader argument with generic types should help");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveArgumentFailureWithoutParameterName() {
|
||||
DataFetchingEnvironment environment = initEnvironment(registry ->
|
||||
registry.forName("namedDataLoader").registerBatchLoader((ids, env) -> Flux.empty()));
|
||||
this.registry.forName("namedDataLoader").registerBatchLoader((ids, env) -> Flux.empty());
|
||||
|
||||
MethodParameter parameter = initParameter(1);
|
||||
// Skip ParameterNameDiscovery
|
||||
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(parameter, environment))
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(parameter, environment()))
|
||||
.hasMessageContaining("compiling with \"-parameters\" should help");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveArgumentFailureNoMatch() {
|
||||
DataFetchingEnvironment environment = initEnvironment(registry ->
|
||||
registry.forName("bookDataLoader").registerBatchLoader((ids, env) -> Flux.empty()));
|
||||
this.registry.forName("bookDataLoader").registerBatchLoader((ids, env) -> Flux.empty());
|
||||
|
||||
MethodParameter parameter = initParameter(0);
|
||||
parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
|
||||
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(parameter, environment))
|
||||
assertThatThrownBy(() -> this.resolver.resolveArgument(parameter, environment()))
|
||||
.hasMessageContaining(
|
||||
"Neither the name of the declared value type 'class org.springframework.graphql.Author' " +
|
||||
"nor the method parameter name 'authorDataLoader' match to any DataLoader. " +
|
||||
"The DataLoaderRegistry contains: [bookDataLoader]");
|
||||
}
|
||||
|
||||
private DataFetchingEnvironment initEnvironment(Consumer<BatchLoaderRegistry> registryConsumer) {
|
||||
BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
|
||||
registryConsumer.accept(batchLoaderRegistry);
|
||||
|
||||
DataLoaderRegistry registry = DataLoaderRegistry.newRegistry().build();
|
||||
batchLoaderRegistry.registerDataLoaders(registry, GraphQLContext.newContext().build());
|
||||
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment().dataLoaderRegistry(registry).build();
|
||||
private DataFetchingEnvironment environment() {
|
||||
DataLoaderRegistry dataLoaderRegistry = DataLoaderRegistry.newRegistry().build();
|
||||
this.registry.registerDataLoaders(dataLoaderRegistry, GraphQLContext.newContext().build());
|
||||
return DataFetchingEnvironmentImpl.newDataFetchingEnvironment().dataLoaderRegistry(dataLoaderRegistry).build();
|
||||
}
|
||||
|
||||
private MethodParameter initParameter(int index) {
|
||||
|
||||
@@ -32,7 +32,6 @@ import reactor.test.StepVerifier;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.graphql.Author;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.BookCriteria;
|
||||
@@ -77,7 +76,7 @@ public class SchemaMappingInvocationTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
Map<String, Object> book = GraphQlTestUtils.checkErrorsAndGetData(result, "bookById");
|
||||
Map<String, Object> book = GraphQlTestUtils.getData(result, "bookById");
|
||||
assertThat(book.get("id")).isEqualTo("1");
|
||||
assertThat(book.get("name")).isEqualTo("Nineteen Eighty-Four");
|
||||
|
||||
@@ -99,7 +98,7 @@ public class SchemaMappingInvocationTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
List<Map<String, Object>> bookList = GraphQlTestUtils.checkErrorsAndGetData(result, "booksByCriteria");
|
||||
List<Map<String, Object>> bookList = GraphQlTestUtils.getData(result, "booksByCriteria");
|
||||
|
||||
assertThat(bookList).hasSize(2);
|
||||
assertThat(bookList.get(0).get("name")).isEqualTo("Nineteen Eighty-Four");
|
||||
@@ -127,7 +126,7 @@ public class SchemaMappingInvocationTests {
|
||||
.execute(requestInput)
|
||||
.block();
|
||||
|
||||
Map<String, Object> author = GraphQlTestUtils.checkErrorsAndGetData(result, "authorById");
|
||||
Map<String, Object> author = GraphQlTestUtils.getData(result, "authorById");
|
||||
|
||||
assertThat(author.get("id")).isEqualTo("101");
|
||||
assertThat(author.get("firstName")).isEqualTo("George");
|
||||
@@ -150,7 +149,7 @@ public class SchemaMappingInvocationTests {
|
||||
.execute(new RequestInput(operation, null, null, null))
|
||||
.block();
|
||||
|
||||
Map<String, Object> author = GraphQlTestUtils.checkErrorsAndGetData(result, "addAuthor");
|
||||
Map<String, Object> author = GraphQlTestUtils.getData(result, "addAuthor");
|
||||
assertThat(author.get("id")).isEqualTo("99");
|
||||
assertThat(author.get("firstName")).isEqualTo("James");
|
||||
assertThat(author.get("lastName")).isEqualTo("Joyce");
|
||||
@@ -169,10 +168,10 @@ public class SchemaMappingInvocationTests {
|
||||
.execute(new RequestInput(operation, null, null, null))
|
||||
.block();
|
||||
|
||||
Publisher<ExecutionResult> publisher = GraphQlTestUtils.checkErrorsAndGetData(result);
|
||||
Publisher<ExecutionResult> publisher = GraphQlTestUtils.getData(result);
|
||||
|
||||
Flux<Map<String, Object>> bookFlux = Flux.from(publisher).map(rs -> {
|
||||
Map<String, Object> map = rs.getData();
|
||||
Flux<Map<String, Object>> bookFlux = Flux.from(publisher).map(executionResult -> {
|
||||
Map<String, Object> map = executionResult.getData();
|
||||
return (Map<String, Object>) map.get("bookSearch");
|
||||
});
|
||||
|
||||
@@ -207,22 +206,15 @@ public class SchemaMappingInvocationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GraphQlService graphQlService(GraphQlSource graphQlSource) {
|
||||
ExecutionGraphQlService service = new ExecutionGraphQlService(graphQlSource);
|
||||
public GraphQlService graphQlService(AnnotatedControllerConfigurer configurer) {
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(BookSource.schema, configurer).build();
|
||||
ExecutionGraphQlService service = new ExecutionGraphQlService(source);
|
||||
service.addDataLoaderRegistrar(batchLoaderRegistry());
|
||||
return service;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GraphQlSource graphQlSource() {
|
||||
return GraphQlSource.builder()
|
||||
.schemaResources(new ClassPathResource("books/schema.graphqls"))
|
||||
.configureRuntimeWiring(annotatedDataFetcherConfigurer())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnnotatedControllerConfigurer annotatedDataFetcherConfigurer() {
|
||||
public AnnotatedControllerConfigurer annotatedControllerConfigurer() {
|
||||
return new AnnotatedControllerConfigurer();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,20 @@ package org.springframework.graphql.data.querydsl;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.GraphQLTypeVisitor;
|
||||
import graphql.schema.idl.TypeRuntimeWiring;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplate;
|
||||
import org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactory;
|
||||
import org.springframework.data.map.MapKeyValueAdapter;
|
||||
@@ -42,9 +42,12 @@ import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.graphql.Author;
|
||||
import org.springframework.graphql.BookSource;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.data.GraphQlRepository;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.graphql.web.WebGraphQlHandler;
|
||||
import org.springframework.graphql.web.WebInput;
|
||||
import org.springframework.graphql.web.WebOutput;
|
||||
@@ -62,32 +65,29 @@ import static org.mockito.Mockito.when;
|
||||
*/
|
||||
class QuerydslDataFetcherTests {
|
||||
|
||||
private KeyValueRepositoryFactory repositoryFactory = new KeyValueRepositoryFactory(new KeyValueTemplate(new MapKeyValueAdapter()));
|
||||
private MockRepository mockRepository = repositoryFactory.getRepository(MockRepository.class);
|
||||
private final KeyValueRepositoryFactory repositoryFactory =
|
||||
new KeyValueRepositoryFactory(new KeyValueTemplate(new MapKeyValueAdapter()));
|
||||
|
||||
private final MockRepository mockRepository = repositoryFactory.getRepository(MockRepository.class);
|
||||
|
||||
|
||||
@Test
|
||||
void shouldFetchSingleItems() {
|
||||
Book book = new Book(42L, "Hitchhiker's Guide to the Galaxy", new Author(0L, "Douglas", "Adams"));
|
||||
mockRepository.save(book);
|
||||
|
||||
BiConsumer<Consumer<TypeRuntimeWiring.Builder>, QuerydslPredicateExecutor<?>> tester =
|
||||
(wiringConfigurer, executor) -> {
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(wiringConfigurer, executor, null);
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 42) {name}}")).block();
|
||||
Consumer<WebGraphQlHandler> tester = (handler) -> {
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 42) {name}}")).block();
|
||||
|
||||
// TODO: getData interferes with method overrides
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById",
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy")));
|
||||
};
|
||||
Map<String, Object> map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", book.getName());
|
||||
};
|
||||
|
||||
// explicit wiring
|
||||
tester.accept(
|
||||
builder -> builder.dataFetcher("bookById", QuerydslDataFetcher.builder(mockRepository).single()),
|
||||
null);
|
||||
tester.accept(initHandler("bookById", QuerydslDataFetcher.builder(mockRepository).single()));
|
||||
|
||||
// auto registration
|
||||
tester.accept(null, mockRepository);
|
||||
tester.accept(initHandler(builder -> {}, mockRepository, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,24 +96,20 @@ class QuerydslDataFetcherTests {
|
||||
Book book2 = new Book(53L, "Breaking Bad", new Author(0L, "", "Heisenberg"));
|
||||
mockRepository.saveAll(Arrays.asList(book1, book2));
|
||||
|
||||
BiConsumer<Consumer<TypeRuntimeWiring.Builder>, QuerydslPredicateExecutor<?>> tester =
|
||||
(wiringConfigurer, executor) -> {
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(wiringConfigurer, mockRepository, null);
|
||||
WebOutput output = handler.handleRequest(input("{ books {name}}")).block();
|
||||
Consumer<WebGraphQlHandler> tester = (handler) -> {
|
||||
WebOutput output = handler.handleRequest(input("{ books {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("books", Arrays.asList(
|
||||
Collections.singletonMap("name", "Breaking Bad"),
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy"))));
|
||||
};
|
||||
List<Map<String, Object>> data = GraphQlTestUtils.getData(output, "books");
|
||||
assertThat(data).containsExactlyInAnyOrder(
|
||||
Collections.singletonMap("name", "Breaking Bad"),
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy"));
|
||||
};
|
||||
|
||||
// explicit wiring
|
||||
tester.accept(
|
||||
builder -> builder.dataFetcher("books", QuerydslDataFetcher.builder(mockRepository).many()),
|
||||
null);
|
||||
tester.accept(initHandler("books", QuerydslDataFetcher.builder(mockRepository).many()));
|
||||
|
||||
// auto registration
|
||||
tester.accept(null, mockRepository);
|
||||
tester.accept(initHandler(builder -> {}, mockRepository, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,21 +119,21 @@ class QuerydslDataFetcherTests {
|
||||
when(mockRepository.findBy(any(), any())).thenReturn(Optional.of(book));
|
||||
|
||||
// 1) Automatic registration only
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(null, mockRepository, null);
|
||||
WebGraphQlHandler handler = initHandler(builder -> {}, mockRepository, null);
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 1) {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById", Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy")));
|
||||
Map<String, Object> map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", "Hitchhiker's Guide to the Galaxy");
|
||||
|
||||
// 2) Automatic registration and explicit wiring
|
||||
handler = initWebGraphQlHandler(
|
||||
builder -> builder.dataFetcher("bookById", env -> new Book(53L, "Breaking Bad", new Author(0L, "", "Heisenberg"))),
|
||||
mockRepository, null);
|
||||
handler = initHandler(
|
||||
"bookById", env -> new Book(53L, "Breaking Bad", new Author(0L, "", "Heisenberg")),
|
||||
mockRepository);
|
||||
|
||||
output = handler.handleRequest(input("{ bookById(id: 1) {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById", Collections.singletonMap("name", "Breaking Bad")));
|
||||
map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", "Breaking Bad");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,17 +141,13 @@ class QuerydslDataFetcherTests {
|
||||
Book book = new Book(42L, "Hitchhiker's Guide to the Galaxy", new Author(0L, "Douglas", "Adams"));
|
||||
mockRepository.save(book);
|
||||
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(builder -> builder
|
||||
.dataFetcher("bookById", QuerydslDataFetcher
|
||||
.builder(mockRepository)
|
||||
.projectAs(BookProjection.class)
|
||||
.single()));
|
||||
WebGraphQlHandler handler = initHandler("bookById",
|
||||
QuerydslDataFetcher.builder(mockRepository).projectAs(BookProjection.class).single());
|
||||
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 42) {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById",
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy by Douglas Adams")));
|
||||
Map<String, Object> map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", "Hitchhiker's Guide to the Galaxy by Douglas Adams");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,29 +155,24 @@ class QuerydslDataFetcherTests {
|
||||
Book book = new Book(42L, "Hitchhiker's Guide to the Galaxy", new Author(0L, "Douglas", "Adams"));
|
||||
mockRepository.save(book);
|
||||
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(builder -> builder
|
||||
.dataFetcher("bookById", QuerydslDataFetcher
|
||||
.builder(mockRepository)
|
||||
.projectAs(BookDto.class)
|
||||
.single()));
|
||||
WebGraphQlHandler handler = initHandler("bookById",
|
||||
QuerydslDataFetcher.builder(mockRepository).projectAs(BookDto.class).single());
|
||||
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 42) {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById",
|
||||
Collections.singletonMap("name", "The book is: Hitchhiker's Guide to the Galaxy")));
|
||||
Map<String, Object> map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", "The book is: Hitchhiker's Guide to the Galaxy");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConstructPredicateProperly() {
|
||||
MockRepository mockRepository = mock(MockRepository.class);
|
||||
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(builder -> builder
|
||||
.dataFetcher("books", QuerydslDataFetcher
|
||||
.builder(mockRepository)
|
||||
WebGraphQlHandler handler = initHandler("books",
|
||||
QuerydslDataFetcher.builder(mockRepository)
|
||||
.customizer((QuerydslBinderCustomizer<QBook>) (bindings, book) ->
|
||||
bindings.bind(book.name).firstOptional((path, value) -> value.map(path::startsWith)))
|
||||
.many()));
|
||||
.many());
|
||||
|
||||
handler.handleRequest(input("{ books(name: \"H\", author: \"Doug\") {name}}")).block();
|
||||
|
||||
@@ -202,24 +189,18 @@ class QuerydslDataFetcherTests {
|
||||
Book book = new Book(42L, "Hitchhiker's Guide to the Galaxy", new Author(0L, "Douglas", "Adams"));
|
||||
when(mockRepository.findBy(any(), any())).thenReturn(Mono.just(book));
|
||||
|
||||
BiConsumer<Consumer<TypeRuntimeWiring.Builder>, ReactiveQuerydslPredicateExecutor<?>> tester =
|
||||
(wiringConfigurer, executor) -> {
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(wiringConfigurer, null, executor);
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 1) {name}}")).block();
|
||||
Consumer<WebGraphQlHandler> tester = (handler) -> {
|
||||
WebOutput output = handler.handleRequest(input("{ bookById(id: 1) {name}}")).block();
|
||||
|
||||
// TODO: getData interferes with method overrides
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("bookById",
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy")));
|
||||
};
|
||||
Map<String, Object> map = GraphQlTestUtils.getData(output, "bookById");
|
||||
assertThat(map).hasSize(1).containsEntry("name", book.getName());
|
||||
};
|
||||
|
||||
// explicit wiring
|
||||
tester.accept(
|
||||
builder -> builder.dataFetcher("bookById", QuerydslDataFetcher.builder(mockRepository).single()),
|
||||
null);
|
||||
tester.accept(initHandler("bookById", QuerydslDataFetcher.builder(mockRepository).single()));
|
||||
|
||||
// auto registration
|
||||
tester.accept(null, mockRepository);
|
||||
tester.accept(initHandler(builder -> {}, null, mockRepository));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,24 +210,20 @@ class QuerydslDataFetcherTests {
|
||||
Book book2 = new Book(53L, "Breaking Bad", new Author(0L, "", "Heisenberg"));
|
||||
when(mockRepository.findBy(any(), any())).thenReturn(Flux.just(book1, book2));
|
||||
|
||||
BiConsumer<Consumer<TypeRuntimeWiring.Builder>, ReactiveQuerydslPredicateExecutor<?>> tester =
|
||||
(wiringConfigurer, executor) -> {
|
||||
WebGraphQlHandler handler = initWebGraphQlHandler(wiringConfigurer, null, mockRepository);
|
||||
WebOutput output = handler.handleRequest(input("{ books {name}}")).block();
|
||||
Consumer<WebGraphQlHandler> tester = (handler) -> {
|
||||
WebOutput output = handler.handleRequest(input("{ books {name}}")).block();
|
||||
|
||||
assertThat((Object) output.getData()).isEqualTo(
|
||||
Collections.singletonMap("books", Arrays.asList(
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy"),
|
||||
Collections.singletonMap("name", "Breaking Bad"))));
|
||||
};
|
||||
List<Map<String, Object>> data = GraphQlTestUtils.getData(output, "books");
|
||||
assertThat(data).containsExactlyInAnyOrder(
|
||||
Collections.singletonMap("name", "Breaking Bad"),
|
||||
Collections.singletonMap("name", "Hitchhiker's Guide to the Galaxy"));
|
||||
};
|
||||
|
||||
// explicit wiring
|
||||
tester.accept(
|
||||
builder -> builder.dataFetcher("books", QuerydslDataFetcher.builder(mockRepository).many()),
|
||||
null);
|
||||
tester.accept(initHandler("books", QuerydslDataFetcher.builder(mockRepository).many()));
|
||||
|
||||
// auto registration
|
||||
tester.accept(null, mockRepository);
|
||||
tester.accept(initHandler(builder -> {}, null, mockRepository));
|
||||
}
|
||||
|
||||
|
||||
@@ -260,49 +237,48 @@ class QuerydslDataFetcherTests {
|
||||
|
||||
}
|
||||
|
||||
static WebGraphQlHandler initWebGraphQlHandler(Consumer<TypeRuntimeWiring.Builder> configurer) {
|
||||
return initWebGraphQlHandler(configurer, null, null);
|
||||
static WebGraphQlHandler initHandler(String fieldName, DataFetcher<?> fetcher) {
|
||||
return initHandler(fieldName, fetcher, null);
|
||||
}
|
||||
|
||||
static WebGraphQlHandler initWebGraphQlHandler(
|
||||
@Nullable Consumer<TypeRuntimeWiring.Builder> configurer,
|
||||
static WebGraphQlHandler initHandler(
|
||||
String fieldName, DataFetcher<?> fetcher, @Nullable QuerydslPredicateExecutor<?> executor) {
|
||||
|
||||
return initHandler(
|
||||
GraphQlTestUtils.graphQlSource(BookSource.schema, "Query", fieldName, fetcher),
|
||||
executor, null);
|
||||
}
|
||||
|
||||
static WebGraphQlHandler initHandler(
|
||||
RuntimeWiringConfigurer configurer,
|
||||
@Nullable QuerydslPredicateExecutor<?> executor,
|
||||
@Nullable ReactiveQuerydslPredicateExecutor<?> reactiveExecutor) {
|
||||
|
||||
return WebGraphQlHandler
|
||||
.builder(new ExecutionGraphQlService(graphQlSource(configurer, executor, reactiveExecutor)))
|
||||
.build();
|
||||
return initHandler(
|
||||
GraphQlTestUtils.graphQlSource(BookSource.schema, configurer),
|
||||
executor,
|
||||
reactiveExecutor);
|
||||
}
|
||||
|
||||
private static GraphQlSource graphQlSource(
|
||||
@Nullable Consumer<TypeRuntimeWiring.Builder> configurer,
|
||||
private static WebGraphQlHandler initHandler(
|
||||
GraphQlSource.Builder sourceBuilder,
|
||||
@Nullable QuerydslPredicateExecutor<?> executor,
|
||||
@Nullable ReactiveQuerydslPredicateExecutor<?> reactiveExecutor) {
|
||||
|
||||
GraphQlSource.Builder graphQlSourceBuilder = GraphQlSource.builder()
|
||||
.schemaResources(new ClassPathResource("books/schema.graphqls"));
|
||||
|
||||
if (configurer != null) {
|
||||
TypeRuntimeWiring.Builder typeBuilder = TypeRuntimeWiring.newTypeWiring("Query");
|
||||
configurer.accept(typeBuilder);
|
||||
graphQlSourceBuilder.configureRuntimeWiring(wiring -> wiring.type(typeBuilder));
|
||||
}
|
||||
|
||||
GraphQLTypeVisitor visitor = QuerydslDataFetcher.registrationTypeVisitor(
|
||||
(executor != null ? Collections.singletonList(executor) : Collections.emptyList()),
|
||||
(reactiveExecutor != null ? Collections.singletonList(reactiveExecutor): Collections.emptyList()));
|
||||
(reactiveExecutor != null ? Collections.singletonList(reactiveExecutor) : Collections.emptyList()));
|
||||
|
||||
graphQlSourceBuilder.typeVisitors(Collections.singletonList(visitor));
|
||||
|
||||
return graphQlSourceBuilder.build();
|
||||
GraphQlSource source = sourceBuilder.typeVisitors(Collections.singletonList(visitor)).build();
|
||||
ExecutionGraphQlService service = new ExecutionGraphQlService(source);
|
||||
return WebGraphQlHandler.builder(service).build();
|
||||
}
|
||||
|
||||
private WebInput input(String query) {
|
||||
return new WebInput(
|
||||
URI.create("http://abc.org"), new HttpHeaders(), Collections.singletonMap("query", query),
|
||||
null, "1");
|
||||
return new WebInput(URI.create("/"), new HttpHeaders(), Collections.singletonMap("query", query), null, "1");
|
||||
}
|
||||
|
||||
|
||||
interface BookProjection {
|
||||
|
||||
@Value("#{target.name + ' by ' + target.author.firstName + ' ' + target.author.lastName}")
|
||||
|
||||
@@ -24,10 +24,10 @@ import org.dataloader.DataLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.graphql.Author;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.BookSource;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.RequestInput;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -40,8 +40,23 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class BatchLoadingTests {
|
||||
|
||||
private final BatchLoaderRegistry registry = new DefaultBatchLoaderRegistry();
|
||||
|
||||
|
||||
@Test
|
||||
void batchLoader() {
|
||||
String query = "{ " +
|
||||
" booksByCriteria(criteria: {author:\"Orwell\"}) { " +
|
||||
" author {" +
|
||||
" firstName, " +
|
||||
" lastName " +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
this.registry.forTypePair(Long.class, Author.class)
|
||||
.registerBatchLoader((ids, env) -> Flux.fromIterable(ids).map(BookSource::getAuthor));
|
||||
|
||||
ExecutionGraphQlService service = initExecutionGraphQlService(wiring -> {
|
||||
wiring.type("Query", builder -> builder.dataFetcher("booksByCriteria", env -> {
|
||||
Map<String, Object> criteria = env.getArgument("criteria");
|
||||
@@ -57,23 +72,7 @@ public class BatchLoadingTests {
|
||||
}));
|
||||
});
|
||||
|
||||
BatchLoaderRegistry registry = new DefaultBatchLoaderRegistry();
|
||||
registry.forTypePair(Long.class, Author.class)
|
||||
.registerBatchLoader((ids, env) -> Flux.fromIterable(ids).map(BookSource::getAuthor));
|
||||
|
||||
service.addDataLoaderRegistrar(registry);
|
||||
|
||||
String query = "{ " +
|
||||
" booksByCriteria(criteria: {author:\"Orwell\"}) { " +
|
||||
" author {" +
|
||||
" firstName, " +
|
||||
" lastName " +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
RequestInput input = new RequestInput(query, null, null, null);
|
||||
ExecutionResult result = service.execute(input).block();
|
||||
ExecutionResult result = service.execute(new RequestInput(query, null, null, null)).block();
|
||||
|
||||
assertThat(result.getErrors()).isEmpty();
|
||||
Map<String, Object> data = result.getData();
|
||||
@@ -88,11 +87,10 @@ public class BatchLoadingTests {
|
||||
}
|
||||
|
||||
private ExecutionGraphQlService initExecutionGraphQlService(RuntimeWiringConfigurer configurer) {
|
||||
GraphQlSource graphQlSource = GraphQlSource.builder()
|
||||
.schemaResources(new ClassPathResource("books/schema.graphqls"))
|
||||
.configureRuntimeWiring(configurer)
|
||||
.build();
|
||||
return new ExecutionGraphQlService(graphQlSource);
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(BookSource.schema, configurer).build();
|
||||
ExecutionGraphQlService service = new ExecutionGraphQlService(source);
|
||||
service.addDataLoaderRegistrar(this.registry);
|
||||
return service;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ClassNameTypeResolverTests {
|
||||
void typeResolutionViaSuperHierarchy() {
|
||||
|
||||
GraphQlSource graphQlSource =
|
||||
GraphQlTestUtils.initGraphQlSource(schema, "Query", "animals", env -> animalList).build();
|
||||
GraphQlTestUtils.graphQlSource(schema, "Query", "animals", env -> animalList).build();
|
||||
|
||||
String query = "" +
|
||||
"query Animals {" +
|
||||
@@ -87,7 +87,7 @@ public class ClassNameTypeResolverTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
List<Map<String, Object>> actualAnimals = GraphQlTestUtils.checkErrorsAndGetData(result, "animals");
|
||||
List<Map<String, Object>> actualAnimals = GraphQlTestUtils.getData(result, "animals");
|
||||
|
||||
for (int i = 0; i < animalList.size(); i++) {
|
||||
Map<String, Object> actualAnimal = actualAnimals.get(i);
|
||||
@@ -113,7 +113,7 @@ public class ClassNameTypeResolverTests {
|
||||
typeResolver.addMapping(Tree.class, "Plant");
|
||||
|
||||
GraphQlSource graphQlSource =
|
||||
GraphQlTestUtils.initGraphQlSource(schema, "Query", "sightings", env -> animalAndPlantList)
|
||||
GraphQlTestUtils.graphQlSource(schema, "Query", "sightings", env -> animalAndPlantList)
|
||||
.defaultTypeResolver(typeResolver)
|
||||
.build();
|
||||
|
||||
@@ -137,7 +137,7 @@ public class ClassNameTypeResolverTests {
|
||||
.execute(new RequestInput(query, null, null, null))
|
||||
.block();
|
||||
|
||||
List<Map<String, Object>> actualSightings = GraphQlTestUtils.checkErrorsAndGetData(result, "sightings");
|
||||
List<Map<String, Object>> actualSightings = GraphQlTestUtils.getData(result, "sightings");
|
||||
|
||||
for (int i = 0; i < animalAndPlantList.size(); i++) {
|
||||
Map<String, Object> actualSighting = actualSightings.get(i);
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
import graphql.ExecutionInput;
|
||||
import graphql.ExecutionResult;
|
||||
import graphql.GraphQL;
|
||||
import graphql.schema.DataFetcher;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -37,13 +38,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContextDataFetcherDecorator}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ContextDataFetcherDecoratorTests {
|
||||
|
||||
@Test
|
||||
void monoDataFetcher() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> Mono.deferContextual((context) -> {
|
||||
GraphQL graphQl = initGraphQl(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", (env) -> Mono.deferContextual((context) -> {
|
||||
Object name = context.get("name");
|
||||
return Mono.delay(Duration.ofMillis(50)).map((aLong) -> "Hello " + name);
|
||||
}));
|
||||
@@ -58,25 +61,29 @@ public class ContextDataFetcherDecoratorTests {
|
||||
|
||||
@Test
|
||||
void fluxDataFetcher() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greetings: [String] }", "Query", "greetings",
|
||||
(env) -> Mono.delay(Duration.ofMillis(50)).flatMapMany((aLong) -> Flux.deferContextual((context) -> {
|
||||
String name = context.get("name");
|
||||
return Flux.just("Hi", "Bonjour", "Hola").map((s) -> s + " " + name);
|
||||
})));
|
||||
GraphQL graphQl = initGraphQl(
|
||||
"type Query { greetings: [String] }",
|
||||
"Query", "greetings",
|
||||
(env) -> Mono.delay(Duration.ofMillis(50))
|
||||
.flatMapMany((aLong) -> Flux.deferContextual((context) -> {
|
||||
String name = context.get("name");
|
||||
return Flux.just("Hi", "Bonjour", "Hola").map((s) -> s + " " + name);
|
||||
})));
|
||||
|
||||
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greetings }").build();
|
||||
ReactorContextManager.setReactorContext(Context.of("name", "007"), input);
|
||||
|
||||
Map<String, Object> data = graphQl.executeAsync(input).get().getData();
|
||||
ExecutionResult result = graphQl.executeAsync(input).get();
|
||||
|
||||
assertThat((List<String>) data.get("greetings")).containsExactly("Hi 007", "Bonjour 007", "Hola 007");
|
||||
List<String> data = GraphQlTestUtils.getData(result, "greetings");
|
||||
assertThat(data).containsExactly("Hi 007", "Bonjour 007", "Hola 007");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fluxDataFetcherSubscription() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(
|
||||
"type Query { greeting: String } type Subscription { greetings: String }", "Subscription", "greetings",
|
||||
(env) -> Mono.delay(Duration.ofMillis(50))
|
||||
GraphQL graphQl = initGraphQl(
|
||||
"type Query { greeting: String } type Subscription { greetings: String }",
|
||||
"Subscription", "greetings", (env) -> Mono.delay(Duration.ofMillis(50))
|
||||
.flatMapMany((aLong) -> Flux.deferContextual((context) -> {
|
||||
String name = context.get("name");
|
||||
return Flux.just("Hi", "Bonjour", "Hola").map((s) -> s + " " + name);
|
||||
@@ -88,8 +95,7 @@ public class ContextDataFetcherDecoratorTests {
|
||||
Publisher<String> publisher = graphQl.executeAsync(input).get().getData();
|
||||
|
||||
List<String> actual = Flux.from(publisher).cast(ExecutionResult.class)
|
||||
.map((result) -> ((Map<String, ?>) result.getData()).get("greetings"))
|
||||
.cast(String.class)
|
||||
.map((result) -> GraphQlTestUtils.<String>getData(result, "greetings"))
|
||||
.collectList()
|
||||
.block();
|
||||
|
||||
@@ -102,9 +108,9 @@ public class ContextDataFetcherDecoratorTests {
|
||||
nameThreadLocal.set("007");
|
||||
TestThreadLocalAccessor<String> accessor = new TestThreadLocalAccessor<>(nameThreadLocal);
|
||||
try {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(
|
||||
"type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> "Hello " + nameThreadLocal.get());
|
||||
GraphQL graphQl = initGraphQl(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", (env) -> "Hello " + nameThreadLocal.get());
|
||||
|
||||
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
|
||||
ContextView view = ReactorContextManager.extractThreadLocalValues(accessor, Context.empty());
|
||||
@@ -114,7 +120,7 @@ public class ContextDataFetcherDecoratorTests {
|
||||
.flatMap((aLong) -> Mono.fromFuture(graphQl.executeAsync(input)))
|
||||
.block();
|
||||
|
||||
Map<String, Object> data = result.getData();
|
||||
Map<String, Object> data = GraphQlTestUtils.getData(result);
|
||||
assertThat(data).hasSize(1).containsEntry("greeting", "Hello 007");
|
||||
}
|
||||
finally {
|
||||
@@ -122,4 +128,11 @@ public class ContextDataFetcherDecoratorTests {
|
||||
}
|
||||
}
|
||||
|
||||
private static GraphQL initGraphQl(
|
||||
String schemaContent, String typeName, String fieldName, DataFetcher<?> fetcher) {
|
||||
|
||||
return GraphQlTestUtils.graphQlSource(schemaContent, typeName, fieldName, fetcher)
|
||||
.build().graphQl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultBatchLoaderRegistry}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class DefaultBatchLoaderRegistryTests {
|
||||
|
||||
|
||||
@@ -40,16 +40,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ExceptionResolversExceptionHandler}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ExceptionResolversExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
void resolveException() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
(ex, env) -> Mono.just(Collections.singletonList(
|
||||
GraphQL graphQl = initGraphQl((ex, env) ->
|
||||
Mono.just(Collections.singletonList(
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage())
|
||||
.errorType(ErrorType.BAD_REQUEST).build())));
|
||||
@@ -68,11 +66,8 @@ public class ExceptionResolversExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
void resolveExceptionWithReactorContext() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
(ex, env) -> Mono.deferContextual((view) -> Mono.just(Collections.singletonList(
|
||||
GraphQL graphQl = initGraphQl((ex, env) ->
|
||||
Mono.deferContextual((view) -> Mono.just(Collections.singletonList(
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + view.get("name"))
|
||||
.errorType(ErrorType.BAD_REQUEST).build()))));
|
||||
@@ -92,15 +87,11 @@ public class ExceptionResolversExceptionHandlerTests {
|
||||
nameThreadLocal.set("007");
|
||||
TestThreadLocalAccessor<String> accessor = new TestThreadLocalAccessor<>(nameThreadLocal);
|
||||
try {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
threadLocalContextAwareExceptionResolver((ex, env) ->
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + nameThreadLocal.get())
|
||||
.errorType(ErrorType.BAD_REQUEST)
|
||||
.build()));
|
||||
GraphQL graphQl = initGraphQl(threadLocalContextAwareExceptionResolver((ex, env) ->
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + nameThreadLocal.get())
|
||||
.errorType(ErrorType.BAD_REQUEST)
|
||||
.build()));
|
||||
|
||||
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
|
||||
ContextView view = ReactorContextManager.extractThreadLocalValues(accessor, Context.empty());
|
||||
@@ -120,11 +111,7 @@ public class ExceptionResolversExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
void unresolvedException() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
(exception, environment) -> Mono.empty());
|
||||
GraphQL graphQl = initGraphQl((exception, environment) -> Mono.empty());
|
||||
|
||||
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
|
||||
ExecutionResult result = graphQl.executeAsync(input).get();
|
||||
@@ -141,11 +128,7 @@ public class ExceptionResolversExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
void suppressedException() throws Exception {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
(ex, env) -> Mono.just(Collections.emptyList()));
|
||||
GraphQL graphQl = initGraphQl((ex, env) -> Mono.just(Collections.emptyList()));
|
||||
|
||||
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
|
||||
ExecutionResult result = graphQl.executeAsync(input).get();
|
||||
@@ -155,6 +138,17 @@ public class ExceptionResolversExceptionHandlerTests {
|
||||
assertThat(result.getErrors()).hasSize(0);
|
||||
}
|
||||
|
||||
private static GraphQL initGraphQl(DataFetcherExceptionResolver exceptionResolver) {
|
||||
return GraphQlTestUtils.graphQlSource(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", (env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
})
|
||||
.exceptionResolvers(Collections.singletonList(exceptionResolver))
|
||||
.build()
|
||||
.graphQl();
|
||||
}
|
||||
|
||||
private static DataFetcherExceptionResolver threadLocalContextAwareExceptionResolver(
|
||||
BiFunction<Throwable, DataFetchingEnvironment, GraphQLError> resolver) {
|
||||
|
||||
|
||||
@@ -18,11 +18,10 @@ package org.springframework.graphql.web;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import graphql.schema.idl.TypeRuntimeWiring;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.graphql.BookSource;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
|
||||
@@ -61,26 +60,23 @@ public abstract class BookTestUtils {
|
||||
"}";
|
||||
|
||||
public static WebGraphQlHandler initWebGraphQlHandler(WebInterceptor... interceptors) {
|
||||
return WebGraphQlHandler.builder(new ExecutionGraphQlService(graphQlSource()))
|
||||
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(BookSource.schema,
|
||||
wiringBuilder -> {
|
||||
wiringBuilder.type("Query", builder -> builder.dataFetcher("bookById", (env) -> {
|
||||
Long id = Long.parseLong(env.getArgument("id"));
|
||||
return BookSource.getBook(id);
|
||||
}));
|
||||
wiringBuilder.type("Subscription", builder -> builder.dataFetcher("bookSearch", (env) -> {
|
||||
String author = env.getArgument("author");
|
||||
return Flux.fromIterable(BookSource.books())
|
||||
.filter((book) -> book.getAuthor().getFullName().contains(author));
|
||||
}));
|
||||
}).build();
|
||||
|
||||
return WebGraphQlHandler.builder(new ExecutionGraphQlService(source))
|
||||
.interceptors(Arrays.asList(interceptors))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static GraphQlSource graphQlSource() {
|
||||
return GraphQlSource.builder()
|
||||
.schemaResources(new ClassPathResource("books/schema.graphqls"))
|
||||
.configureRuntimeWiring(builder -> builder.type(TypeRuntimeWiring.newTypeWiring("Query")
|
||||
.dataFetcher("bookById", (env) -> {
|
||||
Long id = Long.parseLong(env.getArgument("id"));
|
||||
return BookSource.getBook(id);
|
||||
}))
|
||||
.type(TypeRuntimeWiring.newTypeWiring("Subscription")
|
||||
.dataFetcher("bookSearch", (env) -> {
|
||||
String author = env.getArgument("author");
|
||||
return Flux.fromIterable(BookSource.books())
|
||||
.filter((book) -> book.getAuthor().getFullName().contains(author));
|
||||
})))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import graphql.GraphQL;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.GraphqlErrorBuilder;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
@@ -32,12 +31,12 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.TestGraphQlSource;
|
||||
import org.springframework.graphql.TestThreadLocalAccessor;
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolverAdapter;
|
||||
import org.springframework.graphql.execution.ErrorType;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -53,17 +52,18 @@ public class WebGraphQlHandlerTests {
|
||||
|
||||
@Test
|
||||
void reactorContextPropagation() {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(
|
||||
"type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> Mono.deferContextual((context) -> {
|
||||
GraphQlSource graphQlSource = GraphQlTestUtils.graphQlSource(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", (env) -> Mono.deferContextual((context) -> {
|
||||
Object name = context.get("name");
|
||||
return Mono.delay(Duration.ofMillis(50)).map((aLong) -> "Hello " + name);
|
||||
}));
|
||||
})).build();
|
||||
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlService service = new ExecutionGraphQlService(graphQlSource);
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service).build();
|
||||
|
||||
WebOutput webOutput = handler.handleRequest(webInput).contextWrite((context) -> context.put("name", "007")).block();
|
||||
WebOutput webOutput = handler.handleRequest(webInput)
|
||||
.contextWrite((context) -> context.put("name", "007")).block();
|
||||
|
||||
Map<String, Object> data = webOutput.getData();
|
||||
assertThat(data).hasSize(1).containsEntry("greeting", "Hello 007");
|
||||
@@ -71,19 +71,25 @@ public class WebGraphQlHandlerTests {
|
||||
|
||||
@Test
|
||||
void reactorContextPropagationToExceptionResolver() {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
(ex, env) -> Mono.deferContextual((view) -> Mono.just(Collections.singletonList(
|
||||
GraphqlErrorBuilder
|
||||
.newError(env).message("Resolved error: " + ex.getMessage() + ", name=" + view.get("name"))
|
||||
.errorType(ErrorType.BAD_REQUEST).build()))));
|
||||
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlSource graphQlSource = GraphQlTestUtils.graphQlSource(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", (env) -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
})
|
||||
.exceptionResolvers(Collections.singletonList(
|
||||
(ex, env) -> Mono.deferContextual((view) -> Mono.just(Collections.singletonList(
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + view.get("name"))
|
||||
.errorType(ErrorType.BAD_REQUEST)
|
||||
.build())))))
|
||||
.build();
|
||||
|
||||
GraphQlService service = new ExecutionGraphQlService(graphQlSource);
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service).build();
|
||||
|
||||
WebOutput webOutput = handler.handleRequest(webInput).contextWrite((context) -> context.put("name", "007")).block();
|
||||
WebOutput webOutput = handler.handleRequest(webInput)
|
||||
.contextWrite((context) -> context.put("name", "007")).block();
|
||||
|
||||
Map<String, Object> data = webOutput.getData();
|
||||
assertThat(data).hasSize(1).containsEntry("greeting", null);
|
||||
@@ -99,11 +105,12 @@ public class WebGraphQlHandlerTests {
|
||||
nameThreadLocal.set("007");
|
||||
TestThreadLocalAccessor<String> threadLocalAccessor = new TestThreadLocalAccessor<>(nameThreadLocal);
|
||||
try {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(
|
||||
"type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> "Hello " + nameThreadLocal.get());
|
||||
GraphQlSource graphQlSource = GraphQlTestUtils.graphQlSource(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", env -> "Hello " + nameThreadLocal.get())
|
||||
.build();
|
||||
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlService service = new ExecutionGraphQlService(graphQlSource);
|
||||
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service)
|
||||
.interceptor((input, next) -> Mono.delay(Duration.ofMillis(10)).flatMap((aLong) -> next.next(input)))
|
||||
@@ -125,16 +132,20 @@ public class WebGraphQlHandlerTests {
|
||||
nameThreadLocal.set("007");
|
||||
TestThreadLocalAccessor<String> threadLocalAccessor = new TestThreadLocalAccessor<>(nameThreadLocal);
|
||||
try {
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl("type Query { greeting: String }", "Query", "greeting",
|
||||
(env) -> {
|
||||
GraphQlSource graphQlSource = GraphQlTestUtils.graphQlSource(
|
||||
"type Query { greeting: String }",
|
||||
"Query", "greeting", env -> {
|
||||
throw new IllegalArgumentException("Invalid greeting");
|
||||
},
|
||||
threadLocalContextAwareExceptionResolver((ex, env) ->
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + nameThreadLocal.get())
|
||||
.errorType(ErrorType.BAD_REQUEST).build()));
|
||||
})
|
||||
.exceptionResolvers(Collections.singletonList(
|
||||
threadLocalContextAwareExceptionResolver((ex, env) ->
|
||||
GraphqlErrorBuilder.newError(env)
|
||||
.message("Resolved error: " + ex.getMessage() + ", name=" + nameThreadLocal.get())
|
||||
.errorType(ErrorType.BAD_REQUEST).build())
|
||||
))
|
||||
.build();
|
||||
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlService service = new ExecutionGraphQlService(graphQlSource);
|
||||
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service)
|
||||
.interceptor((input, next) -> Mono.delay(Duration.ofMillis(10)).flatMap((aLong) -> next.next(input)))
|
||||
|
||||
@@ -20,15 +20,14 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import graphql.GraphQL;
|
||||
import graphql.schema.DataFetcher;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.TestGraphQlSource;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.graphql.web.WebGraphQlHandler;
|
||||
import org.springframework.http.codec.EncoderHttpMessageWriter;
|
||||
import org.springframework.http.codec.HttpMessageWriter;
|
||||
@@ -68,8 +67,8 @@ public class GraphQlHttpHandlerTests {
|
||||
private GraphQlHttpHandler createHttpHandler(
|
||||
String schemaContent, String type, String field, DataFetcher<Object> dataFetcher) {
|
||||
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(schemaContent, type, field, dataFetcher);
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(schemaContent, type, field, dataFetcher).build();
|
||||
GraphQlService service = new ExecutionGraphQlService(source);
|
||||
return new GraphQlHttpHandler(WebGraphQlHandler.builder(service).build());
|
||||
}
|
||||
|
||||
|
||||
@@ -23,15 +23,14 @@ import java.util.Locale;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import graphql.GraphQL;
|
||||
import graphql.schema.DataFetcher;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlTestUtils;
|
||||
import org.springframework.graphql.TestGraphQlSource;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.graphql.web.WebGraphQlHandler;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
@@ -78,8 +77,8 @@ public class GraphQlHttpHandlerTests {
|
||||
private GraphQlHttpHandler createHttpHandler(
|
||||
String schemaContent, String type, String field, DataFetcher<Object> dataFetcher) {
|
||||
|
||||
GraphQL graphQl = GraphQlTestUtils.initGraphQl(schemaContent, type, field, dataFetcher);
|
||||
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
|
||||
GraphQlSource source = GraphQlTestUtils.graphQlSource(schemaContent, type, field, dataFetcher).build();
|
||||
GraphQlService service = new ExecutionGraphQlService(source);
|
||||
return new GraphQlHttpHandler(WebGraphQlHandler.builder(service).build());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user