Auto-configure Query* support for GraphQL

This commit auto-configures Spring Data Querydsl and QueryByExample
support for Spring GraphQL.

See gh-29140
This commit is contained in:
Brian Clozel 2021-12-21 08:33:43 +01:00
parent ce6747ccd6
commit 9954b4c63e
13 changed files with 684 additions and 0 deletions

View File

@ -225,6 +225,7 @@ dependencies {
testImplementation("com.github.h-thurow:simple-jndi")
testImplementation("com.ibm.db2:jcc")
testImplementation("com.jayway.jsonpath:json-path")
testImplementation("com.querydsl:querydsl-core")
testImplementation("com.squareup.okhttp3:mockwebserver")
testImplementation("com.sun.xml.messaging.saaj:saaj-impl")
testImplementation("io.projectreactor:reactor-test")
@ -243,6 +244,7 @@ dependencies {
testImplementation("org.mockito:mockito-core")
testImplementation("org.mockito:mockito-junit-jupiter")
testImplementation("org.springframework:spring-test")
testImplementation("org.springframework.graphql:spring-graphql-test")
testImplementation("org.springframework.kafka:spring-kafka-test")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("org.testcontainers:cassandra")

View File

@ -0,0 +1,71 @@
/*
* 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.boot.autoconfigure.graphql.data;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import graphql.GraphQL;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.query.QueryByExampleExecutor;
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.graphql.data.query.QueryByExampleDataFetcher;
import org.springframework.graphql.execution.GraphQlSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} that creates a
* {@link GraphQlSourceBuilderCustomizer}s to detect Spring Data repositories with Query
* By Example support and register them as {@code DataFetcher}s for any queries with a
* matching return type.
*
* @author Rossen Stoyanchev
* @since 2.7.0
* @see QueryByExampleDataFetcher#autoRegistrationTypeVisitor(List, List)
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GraphQL.class, QueryByExampleDataFetcher.class, QueryByExampleExecutor.class })
@ConditionalOnBean(GraphQlSource.class)
@AutoConfigureAfter(GraphQlAutoConfiguration.class)
public class GraphQlQueryByExampleAutoConfiguration {
@Bean
public GraphQlSourceBuilderCustomizer queryByExampleRegistrar(
ObjectProvider<QueryByExampleExecutor<?>> executorsProvider,
ObjectProvider<ReactiveQueryByExampleExecutor<?>> reactiveExecutorsProvider) {
return (builder) -> {
List<QueryByExampleExecutor<?>> executors = executorsProvider.stream().collect(Collectors.toList());
List<ReactiveQueryByExampleExecutor<?>> reactiveExecutors = reactiveExecutorsProvider.stream()
.collect(Collectors.toList());
if (!executors.isEmpty()) {
builder.typeVisitors(Collections.singletonList(
QueryByExampleDataFetcher.autoRegistrationTypeVisitor(executors, reactiveExecutors)));
}
};
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.boot.autoconfigure.graphql.data;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import graphql.GraphQL;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor;
import org.springframework.graphql.data.query.QuerydslDataFetcher;
import org.springframework.graphql.execution.GraphQlSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} that creates a
* {@link GraphQlSourceBuilderCustomizer}s to detect Spring Data repositories with
* Querydsl support and register them as {@code DataFetcher}s for any queries with a
* matching return type.
*
* @author Rossen Stoyanchev
* @since 2.7.0
* @see QuerydslDataFetcher#autoRegistrationTypeVisitor(List, List)
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GraphQL.class, QuerydslDataFetcher.class, QuerydslPredicateExecutor.class })
@ConditionalOnBean(GraphQlSource.class)
@AutoConfigureAfter(GraphQlAutoConfiguration.class)
public class GraphQlQuerydslAutoConfiguration {
@Bean
public GraphQlSourceBuilderCustomizer querydslRegistrar(
ObjectProvider<QuerydslPredicateExecutor<?>> executorsProvider,
ObjectProvider<ReactiveQuerydslPredicateExecutor<?>> reactiveExecutorsProvider) {
return (builder) -> {
List<QuerydslPredicateExecutor<?>> executors = executorsProvider.stream().collect(Collectors.toList());
List<ReactiveQuerydslPredicateExecutor<?>> reactiveExecutors = reactiveExecutorsProvider.stream()
.collect(Collectors.toList());
if (!executors.isEmpty()) {
builder.typeVisitors(Collections
.singletonList(QuerydslDataFetcher.autoRegistrationTypeVisitor(executors, reactiveExecutors)));
}
};
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.boot.autoconfigure.graphql.data;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import graphql.GraphQL;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.graphql.data.query.QueryByExampleDataFetcher;
import org.springframework.graphql.execution.GraphQlSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} that creates a
* {@link GraphQlSourceBuilderCustomizer}s to detect Spring Data repositories with Query
* By Example support and register them as {@code DataFetcher}s for any queries with a
* matching return type.
*
* @author Rossen Stoyanchev
* @since 2.7.0
* @see QueryByExampleDataFetcher#autoRegistrationTypeVisitor(List, List)
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GraphQL.class, QueryByExampleDataFetcher.class, ReactiveQueryByExampleExecutor.class })
@ConditionalOnBean(GraphQlSource.class)
@AutoConfigureAfter(GraphQlAutoConfiguration.class)
public class GraphQlReactiveQueryByExampleAutoConfiguration {
@Bean
public GraphQlSourceBuilderCustomizer reactiveQueryByExampleRegistrar(
ObjectProvider<ReactiveQueryByExampleExecutor<?>> executorsProvider) {
return (builder) -> {
List<ReactiveQueryByExampleExecutor<?>> executors = executorsProvider.stream().collect(Collectors.toList());
if (!executors.isEmpty()) {
builder.typeVisitors(Collections.singletonList(
QueryByExampleDataFetcher.autoRegistrationTypeVisitor(Collections.emptyList(), executors)));
}
};
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.boot.autoconfigure.graphql.data;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import graphql.GraphQL;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor;
import org.springframework.graphql.data.query.QuerydslDataFetcher;
import org.springframework.graphql.execution.GraphQlSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} that creates a
* {@link GraphQlSourceBuilderCustomizer}s to detect Spring Data repositories with
* Querydsl support and register them as {@code DataFetcher}s for any queries with a
* matching return type.
*
* @author Rossen Stoyanchev
* @since 2.7.0
* @see QuerydslDataFetcher#autoRegistrationTypeVisitor(List, List)
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GraphQL.class, QuerydslDataFetcher.class, ReactiveQuerydslPredicateExecutor.class })
@ConditionalOnBean(GraphQlSource.class)
@AutoConfigureAfter(GraphQlAutoConfiguration.class)
public class GraphQlReactiveQuerydslAutoConfiguration {
@Bean
public GraphQlSourceBuilderCustomizer reactiveQuerydslRegistrar(
ObjectProvider<ReactiveQuerydslPredicateExecutor<?>> executorsProvider) {
return (builder) -> {
List<ReactiveQuerydslPredicateExecutor<?>> executors = executorsProvider.stream()
.collect(Collectors.toList());
if (!executors.isEmpty()) {
builder.typeVisitors(Collections.singletonList(
QuerydslDataFetcher.autoRegistrationTypeVisitor(Collections.emptyList(), executors)));
}
};
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2020-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.
*/
/**
* Auto-configuration classes for data integrations with GraphQL.
*/
package org.springframework.boot.autoconfigure.graphql.data;

View File

@ -69,6 +69,10 @@ org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAuto
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQueryByExampleAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQuerydslAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.data.GraphQlQueryByExampleAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.data.GraphQlQuerydslAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.reactive.GraphQlWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.graphql.servlet.GraphQlWebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\

View File

@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.graphql;
import org.springframework.data.annotation.Id;
/**
* Sample class for
*
@ -23,6 +25,7 @@ package org.springframework.boot.autoconfigure.graphql;
*/
public class Book {
@Id
String id;
String name;

View File

@ -0,0 +1,56 @@
/*
* Copyright 2012-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.boot.autoconfigure.graphql;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.PathMetadataFactory;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.StringPath;
/**
* QBook is a Querydsl query type for Book. This class is usually generated by the
* Querydsl annotation processor.
*/
public class QBook extends EntityPathBase<Book> {
private static final long serialVersionUID = -1932588188L;
public static final QBook book = new QBook("book");
public final StringPath author = createString("author");
public final StringPath id = createString("id");
public final StringPath name = createString("name");
public final NumberPath<Integer> pageCount = createNumber("pageCount", Integer.class);
public QBook(String variable) {
super(Book.class, PathMetadataFactory.forVariable(variable));
}
public QBook(Path<? extends Book> path) {
super(path.getType(), path.getMetadata());
}
public QBook(PathMetadata metadata) {
super(Book.class, metadata);
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012-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.boot.autoconfigure.graphql.data;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.Book;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.test.tester.GraphQlTester;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link GraphQlQueryByExampleAutoConfiguration}
*
* @author Brian Clozel
*/
class GraphQlQueryByExampleAutoConfigurationTests {
private static final Book book = new Book("42", "Test title", 42, "Test Author");
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(GraphQlAutoConfiguration.class, GraphQlQueryByExampleAutoConfiguration.class))
.withUserConfiguration(MockRepositoryConfig.class)
.withPropertyValues("spring.main.web-application-type=reactive");
@Test
void shouldRegisterDataFetcherForQueryByExampleRepositories() {
this.contextRunner.run((context) -> {
GraphQlService graphQlService = context.getBean(GraphQlService.class);
GraphQlTester graphQlTester = GraphQlTester.create(graphQlService);
graphQlTester.query("{ bookById(id: 1) {name}}").execute().path("bookById.name").entity(String.class)
.isEqualTo("Test title");
});
}
@Configuration(proxyBeanMethods = false)
static class MockRepositoryConfig {
@Bean
MockRepository mockRepository() {
MockRepository mockRepository = mock(MockRepository.class);
given(mockRepository.findBy(any(), any())).willReturn(Optional.of(book));
return mockRepository;
}
}
@GraphQlRepository
interface MockRepository extends CrudRepository<Book, Long>, QueryByExampleExecutor<Book> {
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012-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.boot.autoconfigure.graphql.data;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.Book;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.test.tester.GraphQlTester;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link GraphQlQuerydslAutoConfiguration}.
*
* @author Brian Clozel
*/
class GraphQlQuerydslAutoConfigurationTests {
private static final Book book = new Book("42", "Test title", 42, "Test Author");
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(GraphQlAutoConfiguration.class, GraphQlQuerydslAutoConfiguration.class))
.withUserConfiguration(MockRepositoryConfig.class)
.withPropertyValues("spring.main.web-application-type=reactive");
@Test
void shouldRegisterDataFetcherForQueryDslRepositories() {
this.contextRunner.run((context) -> {
GraphQlService graphQlService = context.getBean(GraphQlService.class);
GraphQlTester graphQlTester = GraphQlTester.create(graphQlService);
graphQlTester.query("{ bookById(id: 1) {name}}").execute().path("bookById.name").entity(String.class)
.isEqualTo("Test title");
});
}
@Configuration(proxyBeanMethods = false)
static class MockRepositoryConfig {
@Bean
MockRepository mockRepository() {
MockRepository mockRepository = mock(MockRepository.class);
given(mockRepository.findBy(any(), any())).willReturn(Optional.of(book));
return mockRepository;
}
}
@GraphQlRepository
interface MockRepository extends CrudRepository<Book, Long>, QuerydslPredicateExecutor<Book> {
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2012-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.boot.autoconfigure.graphql.data;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.Book;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.test.tester.GraphQlTester;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link GraphQlReactiveQueryByExampleAutoConfiguration}
*
* @author Brian Clozel
*/
class GraphQlReactiveQueryByExampleAutoConfigurationTests {
private static final Mono<Book> bookPublisher = Mono.just(new Book("42", "Test title", 42, "Test Author"));
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(GraphQlAutoConfiguration.class,
GraphQlReactiveQueryByExampleAutoConfiguration.class))
.withUserConfiguration(MockRepositoryConfig.class)
.withPropertyValues("spring.main.web-application-type=reactive");
@Test
void shouldRegisterDataFetcherForQueryByExampleRepositories() {
this.contextRunner.run((context) -> {
GraphQlService graphQlService = context.getBean(GraphQlService.class);
GraphQlTester graphQlTester = GraphQlTester.create(graphQlService);
graphQlTester.query("{ bookById(id: 1) {name}}").execute().path("bookById.name").entity(String.class)
.isEqualTo("Test title");
});
}
@Configuration(proxyBeanMethods = false)
static class MockRepositoryConfig {
@Bean
MockRepository mockRepository() {
MockRepository mockRepository = mock(MockRepository.class);
given(mockRepository.findBy(any(), any())).willReturn(bookPublisher);
return mockRepository;
}
}
@GraphQlRepository
interface MockRepository extends ReactiveCrudRepository<Book, Long>, ReactiveQueryByExampleExecutor<Book> {
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2012-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.boot.autoconfigure.graphql.data;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.Book;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.test.tester.GraphQlTester;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link GraphQlReactiveQuerydslAutoConfiguration}
*
* @author Brian Clozel
*/
class GraphQlReactiveQuerydslAutoConfigurationTests {
private static final Mono<Book> bookPublisher = Mono.just(new Book("42", "Test title", 42, "Test Author"));
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(GraphQlAutoConfiguration.class,
GraphQlReactiveQuerydslAutoConfiguration.class))
.withUserConfiguration(MockRepositoryConfig.class)
.withPropertyValues("spring.main.web-application-type=reactive");
@Test
void shouldRegisterDataFetcherForQueryDslRepositories() {
this.contextRunner.run((context) -> {
GraphQlService graphQlService = context.getBean(GraphQlService.class);
GraphQlTester graphQlTester = GraphQlTester.create(graphQlService);
graphQlTester.query("{ bookById(id: 1) {name}}").execute().path("bookById.name").entity(String.class)
.isEqualTo("Test title");
});
}
@Configuration(proxyBeanMethods = false)
static class MockRepositoryConfig {
@Bean
MockRepository mockRepository() {
MockRepository mockRepository = mock(MockRepository.class);
given(mockRepository.findBy(any(), any())).willReturn(bookPublisher);
return mockRepository;
}
}
@GraphQlRepository
interface MockRepository extends ReactiveCrudRepository<Book, Long>, ReactiveQuerydslPredicateExecutor<Book> {
}
}