Extract base class for BatchMapping tests
See gh-119
This commit is contained in:
@@ -54,15 +54,16 @@ public class BatchMappingDetectionTests {
|
||||
@Test
|
||||
void registerWithDefaultCoordinates() {
|
||||
|
||||
Map<String, Map<String, DataFetcher>> map =
|
||||
Map<String, Map<String, DataFetcher>> dataFetcherMap =
|
||||
initRuntimeWiringBuilder(BookController.class).build().getDataFetchers();
|
||||
|
||||
assertThat(map).containsOnlyKeys("Book");
|
||||
assertThat(map.get("Book")).containsOnlyKeys(
|
||||
assertThat(dataFetcherMap).containsOnlyKeys("Book");
|
||||
assertThat(dataFetcherMap.get("Book")).containsOnlyKeys(
|
||||
"authorFlux", "authorList", "authorMonoMap", "authorMap", "authorEnvironment");
|
||||
|
||||
DataLoaderRegistry registry = new DataLoaderRegistry();
|
||||
this.batchLoaderRegistry.registerDataLoaders(registry, GraphQLContext.newContext().build());
|
||||
|
||||
assertThat(registry.getDataLoadersMap()).containsOnlyKeys(
|
||||
"Book.authorFlux", "Book.authorList", "Book.authorMonoMap", "Book.authorMap", "Book.authorEnvironment");
|
||||
}
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
*/
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -27,8 +22,6 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import graphql.ExecutionResult;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
@@ -37,17 +30,10 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.graphql.GraphQlResponse;
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlSetup;
|
||||
import org.springframework.graphql.RequestInput;
|
||||
import org.springframework.graphql.data.method.annotation.BatchMapping;
|
||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||
import org.springframework.graphql.execution.BatchLoaderRegistry;
|
||||
import org.springframework.graphql.execution.DefaultBatchLoaderRegistry;
|
||||
import org.springframework.graphql.execution.ExecutionGraphQlService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -60,42 +46,7 @@ import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class BatchMappingInvocationTests {
|
||||
|
||||
private static final Map<Long, Course> courseMap = new HashMap<>();
|
||||
|
||||
private static final Map<Long, Person> personMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
Course.save(11L, "Ethical Hacking", 15L, Arrays.asList(22L, 26L, 31L));
|
||||
Course.save(19L, "Docker and Kubernetes", 17L, Arrays.asList(31L, 39L, 44L, 45L));
|
||||
|
||||
Person.save(15L, "Josh", "Kelly");
|
||||
Person.save(17L, "Albert", "Murray");
|
||||
Person.save(22L, "Bonnie", "Gray");
|
||||
Person.save(26L, "John", "Perry");
|
||||
Person.save(31L, "Alaine", "Baily");
|
||||
Person.save(39L, "Jeff", "Peterson");
|
||||
Person.save(44L, "Jared", "Mccarthy");
|
||||
Person.save(45L, "Benjamin", "Brown");
|
||||
}
|
||||
|
||||
private static final String schema = "" +
|
||||
"type Query {" +
|
||||
" courses: [Course]" +
|
||||
"}" +
|
||||
"type Course {" +
|
||||
" id: ID" +
|
||||
" name: String" +
|
||||
" instructor: Person" +
|
||||
" students: [Person]" +
|
||||
"}" +
|
||||
"type Person {" +
|
||||
" id: ID" +
|
||||
" firstName: String" +
|
||||
" lastName: String" +
|
||||
"}";
|
||||
|
||||
public class BatchMappingInvocationTests extends BatchMappingTestSupport {
|
||||
|
||||
private static Stream<Arguments> controllerClasses() {
|
||||
return Stream.of(
|
||||
@@ -106,6 +57,7 @@ public class BatchMappingInvocationTests {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("controllerClasses")
|
||||
void oneToOne(Class<?> controllerClass) {
|
||||
@@ -121,7 +73,7 @@ public class BatchMappingInvocationTests {
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
Mono<ExecutionResult> resultMono = graphQlService(controllerClass, CourseConfig.class)
|
||||
Mono<ExecutionResult> resultMono = graphQlService(controllerClass)
|
||||
.execute(new RequestInput(query, null, null, null));
|
||||
|
||||
List<Course> actualCourses = GraphQlResponse.from(resultMono).toList("courses", Course.class);
|
||||
@@ -154,7 +106,7 @@ public class BatchMappingInvocationTests {
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
Mono<ExecutionResult> resultMono = graphQlService(controllerClass, CourseConfig.class)
|
||||
Mono<ExecutionResult> resultMono = graphQlService(controllerClass)
|
||||
.execute(new RequestInput(query, null, null, null));
|
||||
|
||||
List<Course> actualCourses = GraphQlResponse.from(resultMono).toList("courses", Course.class);
|
||||
@@ -180,27 +132,19 @@ public class BatchMappingInvocationTests {
|
||||
private ExecutionGraphQlService graphQlService(Class<?>... configClasses) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
applicationContext.register(configClasses);
|
||||
applicationContext.register(BatchMappingTestSupport.CourseConfig.class);
|
||||
applicationContext.refresh();
|
||||
|
||||
return applicationContext.getBean(ExecutionGraphQlService.class);
|
||||
}
|
||||
|
||||
|
||||
private static class CourseController {
|
||||
|
||||
@QueryMapping
|
||||
public Collection<Course> courses() {
|
||||
return courseMap.values();
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
private static class BatchMonoMapController extends CourseController {
|
||||
|
||||
@BatchMapping
|
||||
public Mono<Map<Course, Person>> instructor(List<Course> courses) {
|
||||
return Flux.fromIterable(Course.allCourses())
|
||||
.collect(Collectors.toMap(Function.identity(), Course::instructor));
|
||||
return Flux.fromIterable(courses).collect(Collectors.toMap(Function.identity(), Course::instructor));
|
||||
}
|
||||
|
||||
@BatchMapping
|
||||
@@ -214,8 +158,7 @@ public class BatchMappingInvocationTests {
|
||||
|
||||
@BatchMapping
|
||||
public Map<Course, Person> instructor(List<Course> courses) {
|
||||
return Course.allCourses().stream().collect(
|
||||
Collectors.toMap(Function.identity(), Course::instructor));
|
||||
return courses.stream().collect(Collectors.toMap(Function.identity(), Course::instructor));
|
||||
}
|
||||
|
||||
@BatchMapping
|
||||
@@ -252,143 +195,4 @@ public class BatchMappingInvocationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class CourseConfig {
|
||||
|
||||
@Bean
|
||||
public GraphQlService graphQlService(AnnotatedControllerConfigurer configurer, BatchLoaderRegistry registry) {
|
||||
return GraphQlSetup.schemaContent(schema)
|
||||
.runtimeWiring(configurer)
|
||||
.dataLoaders(registry)
|
||||
.toGraphQlService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnnotatedControllerConfigurer annotatedDataFetcherConfigurer() {
|
||||
return new AnnotatedControllerConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BatchLoaderRegistry batchLoaderRegistry() {
|
||||
return new DefaultBatchLoaderRegistry();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Course {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Long instructorId;
|
||||
|
||||
private final List<Long> studentIds;
|
||||
|
||||
@JsonCreator
|
||||
public Course(
|
||||
@JsonProperty("id") Long id, @JsonProperty("name") String name,
|
||||
@JsonProperty("instructor") @Nullable Person instructor,
|
||||
@JsonProperty("students") @Nullable List<Person> students) {
|
||||
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.instructorId = (instructor != null ? instructor.id() : -1);
|
||||
this.studentIds = (students != null ?
|
||||
students.stream().map(Person::id).collect(Collectors.toList()) :
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
public Course(Long id, String name, Long instructorId, List<Long> studentIds) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.instructorId = instructorId;
|
||||
this.studentIds = studentIds;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Long instructorId() {
|
||||
return this.instructorId;
|
||||
}
|
||||
|
||||
public List<Long> studentIds() {
|
||||
return this.studentIds;
|
||||
}
|
||||
|
||||
public List<Person> students() {
|
||||
return this.studentIds.stream().map(personMap::get).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Person instructor() {
|
||||
return personMap.get(this.instructorId);
|
||||
}
|
||||
|
||||
public static void save(Long id, String name, Long instructorId, List<Long> studentIds) {
|
||||
Course course = new Course(id, name, instructorId, studentIds);
|
||||
courseMap.put(id, course);
|
||||
}
|
||||
|
||||
public static List<Course> allCourses() {
|
||||
return new ArrayList<>(courseMap.values());
|
||||
}
|
||||
|
||||
// Course is a key in the DataLoader map
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.id.equals(((Course) other).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Person {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String firstName;
|
||||
|
||||
private final String lastName;
|
||||
|
||||
@JsonCreator
|
||||
public Person(
|
||||
@JsonProperty("id") Long id,
|
||||
@JsonProperty("firstName") String firstName,
|
||||
@JsonProperty("lastName") String lastName) {
|
||||
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String firstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public String lastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public static void save(Long id, String firstName, String lastName) {
|
||||
Person person = new Person(id, firstName, lastName);
|
||||
personMap.put(id, person);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.data.method.annotation.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.graphql.GraphQlService;
|
||||
import org.springframework.graphql.GraphQlSetup;
|
||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||
import org.springframework.graphql.execution.BatchLoaderRegistry;
|
||||
import org.springframework.graphql.execution.DefaultBatchLoaderRegistry;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Support class for {@code @BatchMapping}, and other batch loading tests, that
|
||||
* provides a suitable schema, domain types, mock data, and configuration.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class BatchMappingTestSupport {
|
||||
|
||||
static final Map<Long, Course> courseMap = new HashMap<>();
|
||||
|
||||
static final Map<Long, Person> personMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
Course.save(11L, "Ethical Hacking", 15L, Arrays.asList(22L, 26L, 31L));
|
||||
Course.save(19L, "Docker and Kubernetes", 17L, Arrays.asList(31L, 39L, 44L, 45L));
|
||||
|
||||
Person.save(15L, "Josh", "Kelly");
|
||||
Person.save(17L, "Albert", "Murray");
|
||||
Person.save(22L, "Bonnie", "Gray");
|
||||
Person.save(26L, "John", "Perry");
|
||||
Person.save(31L, "Alaine", "Baily");
|
||||
Person.save(39L, "Jeff", "Peterson");
|
||||
Person.save(44L, "Jared", "Mccarthy");
|
||||
Person.save(45L, "Benjamin", "Brown");
|
||||
}
|
||||
|
||||
static final String schema = "" +
|
||||
"type Query {" +
|
||||
" courses: [Course]" +
|
||||
"}" +
|
||||
"type Course {" +
|
||||
" id: ID" +
|
||||
" name: String" +
|
||||
" instructor: Person" +
|
||||
" students: [Person]" +
|
||||
"}" +
|
||||
"type Person {" +
|
||||
" id: ID" +
|
||||
" firstName: String" +
|
||||
" lastName: String" +
|
||||
"}";
|
||||
|
||||
|
||||
|
||||
static class Course {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Long instructorId;
|
||||
|
||||
private final List<Long> studentIds;
|
||||
|
||||
@JsonCreator
|
||||
public Course(
|
||||
@JsonProperty("id") Long id, @JsonProperty("name") String name,
|
||||
@JsonProperty("instructor") @Nullable Person instructor,
|
||||
@JsonProperty("students") @Nullable List<Person> students) {
|
||||
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.instructorId = (instructor != null ? instructor.id() : -1);
|
||||
this.studentIds = (students != null ?
|
||||
students.stream().map(Person::id).collect(Collectors.toList()) :
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
public Course(Long id, String name, Long instructorId, List<Long> studentIds) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.instructorId = instructorId;
|
||||
this.studentIds = studentIds;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Long instructorId() {
|
||||
return this.instructorId;
|
||||
}
|
||||
|
||||
public List<Long> studentIds() {
|
||||
return this.studentIds;
|
||||
}
|
||||
|
||||
public List<Person> students() {
|
||||
return this.studentIds.stream().map(personMap::get).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Person instructor() {
|
||||
return personMap.get(this.instructorId);
|
||||
}
|
||||
|
||||
public static void save(Long id, String name, Long instructorId, List<Long> studentIds) {
|
||||
Course course = new Course(id, name, instructorId, studentIds);
|
||||
courseMap.put(id, course);
|
||||
}
|
||||
|
||||
public static List<Course> allCourses() {
|
||||
return new ArrayList<>(courseMap.values());
|
||||
}
|
||||
|
||||
// Course is a key in the DataLoader map
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.id.equals(((Course) other).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class Person {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String firstName;
|
||||
|
||||
private final String lastName;
|
||||
|
||||
@JsonCreator
|
||||
public Person(
|
||||
@JsonProperty("id") Long id,
|
||||
@JsonProperty("firstName") String firstName,
|
||||
@JsonProperty("lastName") String lastName) {
|
||||
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String firstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public String lastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public static void save(Long id, String firstName, String lastName) {
|
||||
Person person = new Person(id, firstName, lastName);
|
||||
personMap.put(id, person);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class CourseController {
|
||||
|
||||
@QueryMapping
|
||||
public Collection<Course> courses() {
|
||||
return courseMap.values();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class CourseConfig {
|
||||
|
||||
@Bean
|
||||
public GraphQlService graphQlService(AnnotatedControllerConfigurer configurer, BatchLoaderRegistry registry) {
|
||||
return GraphQlSetup.schemaContent(schema)
|
||||
.runtimeWiring(configurer)
|
||||
.dataLoaders(registry)
|
||||
.toGraphQlService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnnotatedControllerConfigurer annotatedDataFetcherConfigurer() {
|
||||
return new AnnotatedControllerConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BatchLoaderRegistry batchLoaderRegistry() {
|
||||
return new DefaultBatchLoaderRegistry();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user