Add GraphQlTest slice
This commit adds the `@GraphQlTest` annotation which brings a new type of sliced test for GraphQL applications. This considers all the required infrastructure brought by `@AutoConfigureGraphQl`, but also brings application components like `@Controller` beans and `RuntimeWiringConfigurer`. With this type of test, we'll only initialize a minimal setup for testing a set of Controllers, without involving any transport-related component. See gh-29140
This commit is contained in:
		
							parent
							
								
									c0707e4f5b
								
							
						
					
					
						commit
						a34308e5f7
					
				| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.Documented;
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Inherited;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.extension.ExtendWith;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureGraphQlTester;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureWebGraphQlTester;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson;
 | 
			
		||||
import org.springframework.context.annotation.ComponentScan;
 | 
			
		||||
import org.springframework.core.annotation.AliasFor;
 | 
			
		||||
import org.springframework.core.env.Environment;
 | 
			
		||||
import org.springframework.test.context.BootstrapWith;
 | 
			
		||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Annotation to perform GraphQL tests focusing on GraphQL request execution without a Web
 | 
			
		||||
 * layer, and loading only a subset of the application configuration.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * The annotation disables full auto-configuration and instead loads only components
 | 
			
		||||
 * relevant to GraphQL tests, including the following:
 | 
			
		||||
 * <ul>
 | 
			
		||||
 * <li>{@code @Controller}
 | 
			
		||||
 * <li>{@code RuntimeWiringConfigurer}
 | 
			
		||||
 * <li>{@code @JsonComponent}
 | 
			
		||||
 * <li>{@code Converter}
 | 
			
		||||
 * <li>{@code GenericConverter}
 | 
			
		||||
 * </ul>
 | 
			
		||||
 * <p>
 | 
			
		||||
 * The annotation does not automatically load {@code @Component}, {@code @Service},
 | 
			
		||||
 * {@code @Repository}, and other beans.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * By default, tests annotated with {@code @GraphQlTest} have a
 | 
			
		||||
 * {@link org.springframework.graphql.test.tester.GraphQlTester} configured. For more
 | 
			
		||||
 * fine-grained control of the GraphQlTester, use
 | 
			
		||||
 * {@link AutoConfigureGraphQlTester @AutoConfigureGraphQlTester}.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Typically {@code @GraphQlTest} is used in combination with
 | 
			
		||||
 * {@link org.springframework.boot.test.mock.mockito.MockBean @MockBean} or
 | 
			
		||||
 * {@link org.springframework.context.annotation.Import @Import} to load any collaborators
 | 
			
		||||
 * and other components required for the tests.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * To load your full application configuration instead and test via
 | 
			
		||||
 * {@code WebGraphQlTester}, consider using
 | 
			
		||||
 * {@link org.springframework.boot.test.context.SpringBootTest @SpringBootTest} combined
 | 
			
		||||
 * with {@link AutoConfigureWebGraphQlTester @AutoConfigureWebGraphQlTester}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 * @since 2.7.0
 | 
			
		||||
 * @see AutoConfigureGraphQlTester
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.TYPE)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
@Inherited
 | 
			
		||||
@BootstrapWith(GraphQlTestContextBootstrapper.class)
 | 
			
		||||
@ExtendWith(SpringExtension.class)
 | 
			
		||||
@OverrideAutoConfiguration(enabled = false)
 | 
			
		||||
@TypeExcludeFilters(GraphQlTypeExcludeFilter.class)
 | 
			
		||||
@AutoConfigureCache
 | 
			
		||||
@AutoConfigureJson
 | 
			
		||||
@AutoConfigureGraphQl
 | 
			
		||||
@AutoConfigureGraphQlTester
 | 
			
		||||
@ImportAutoConfiguration
 | 
			
		||||
public @interface GraphQlTest {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Properties in form {@literal key=value} that should be added to the Spring
 | 
			
		||||
	 * {@link Environment} before the test runs.
 | 
			
		||||
	 * @return the properties to add
 | 
			
		||||
	 */
 | 
			
		||||
	String[] properties() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Specifies the controllers to test. This is an alias of {@link #controllers()} which
 | 
			
		||||
	 * can be used for brevity if no other attributes are defined. See
 | 
			
		||||
	 * {@link #controllers()} for details.
 | 
			
		||||
	 * @see #controllers()
 | 
			
		||||
	 * @return the controllers to test
 | 
			
		||||
	 */
 | 
			
		||||
	@AliasFor("controllers")
 | 
			
		||||
	Class<?>[] value() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Specifies the controllers to test. May be left blank if all {@code @Controller}
 | 
			
		||||
	 * beans should be added to the application context.
 | 
			
		||||
	 * @see #value()
 | 
			
		||||
	 * @return the controllers to test
 | 
			
		||||
	 */
 | 
			
		||||
	@AliasFor("value")
 | 
			
		||||
	Class<?>[] controllers() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Determines if default filtering should be used with
 | 
			
		||||
	 * {@link SpringBootApplication @SpringBootApplication}. By default, only
 | 
			
		||||
	 * {@code @Controller} (when no explicit {@link #controllers() controllers} are
 | 
			
		||||
	 * defined), {@code RuntimeWiringConfigurer}, {@code @JsonComponent},
 | 
			
		||||
	 * {@code Converter}, and {@code GenericConverter} beans are included.
 | 
			
		||||
	 * @see #includeFilters()
 | 
			
		||||
	 * @see #excludeFilters()
 | 
			
		||||
	 * @return if default filters should be used
 | 
			
		||||
	 */
 | 
			
		||||
	boolean useDefaultFilters() default true;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * A set of include filters which can be used to add otherwise filtered beans to the
 | 
			
		||||
	 * application context.
 | 
			
		||||
	 * @return include filters to apply
 | 
			
		||||
	 */
 | 
			
		||||
	ComponentScan.Filter[] includeFilters() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * A set of exclude filters which can be used to filter beans that would otherwise be
 | 
			
		||||
	 * added to the application context.
 | 
			
		||||
	 * @return exclude filters to apply
 | 
			
		||||
	 */
 | 
			
		||||
	ComponentScan.Filter[] excludeFilters() default {};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Auto-configuration exclusions that should be applied for this test.
 | 
			
		||||
	 * @return auto-configuration exclusions to apply
 | 
			
		||||
	 */
 | 
			
		||||
	@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
 | 
			
		||||
	Class<?>[] excludeAutoConfiguration() default {};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.LinkedHashSet;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.context.TypeExcludeFilter;
 | 
			
		||||
import org.springframework.boot.jackson.JsonComponent;
 | 
			
		||||
import org.springframework.boot.test.autoconfigure.filter.StandardAnnotationCustomizableTypeExcludeFilter;
 | 
			
		||||
import org.springframework.core.convert.converter.Converter;
 | 
			
		||||
import org.springframework.core.convert.converter.GenericConverter;
 | 
			
		||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.util.ClassUtils;
 | 
			
		||||
import org.springframework.util.ObjectUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link TypeExcludeFilter} for {@link GraphQlTest @GraphQlTest}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 * @since 2.7.0
 | 
			
		||||
 */
 | 
			
		||||
public class GraphQlTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<GraphQlTest> {
 | 
			
		||||
 | 
			
		||||
	private static final Class<?>[] NO_CONTROLLERS = {};
 | 
			
		||||
 | 
			
		||||
	private static final String[] OPTIONAL_INCLUDES = { "com.fasterxml.jackson.databind.Module" };
 | 
			
		||||
 | 
			
		||||
	private static final Set<Class<?>> DEFAULT_INCLUDES;
 | 
			
		||||
 | 
			
		||||
	static {
 | 
			
		||||
		Set<Class<?>> includes = new LinkedHashSet<>();
 | 
			
		||||
		includes.add(JsonComponent.class);
 | 
			
		||||
		includes.add(RuntimeWiringConfigurer.class);
 | 
			
		||||
		includes.add(Converter.class);
 | 
			
		||||
		includes.add(GenericConverter.class);
 | 
			
		||||
		for (String optionalInclude : OPTIONAL_INCLUDES) {
 | 
			
		||||
			try {
 | 
			
		||||
				includes.add(ClassUtils.forName(optionalInclude, null));
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception ex) {
 | 
			
		||||
				// Ignore
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		DEFAULT_INCLUDES = Collections.unmodifiableSet(includes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static final Set<Class<?>> DEFAULT_INCLUDES_AND_CONTROLLER;
 | 
			
		||||
 | 
			
		||||
	static {
 | 
			
		||||
		Set<Class<?>> includes = new LinkedHashSet<>(DEFAULT_INCLUDES);
 | 
			
		||||
		includes.add(Controller.class);
 | 
			
		||||
		DEFAULT_INCLUDES_AND_CONTROLLER = Collections.unmodifiableSet(includes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private final Class<?>[] controllers;
 | 
			
		||||
 | 
			
		||||
	GraphQlTypeExcludeFilter(Class<?> testClass) {
 | 
			
		||||
		super(testClass);
 | 
			
		||||
		this.controllers = getAnnotation().getValue("controllers", Class[].class).orElse(NO_CONTROLLERS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected Set<Class<?>> getDefaultIncludes() {
 | 
			
		||||
		if (ObjectUtils.isEmpty(this.controllers)) {
 | 
			
		||||
			return DEFAULT_INCLUDES_AND_CONTROLLER;
 | 
			
		||||
		}
 | 
			
		||||
		return DEFAULT_INCLUDES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected Set<Class<?>> getComponentIncludes() {
 | 
			
		||||
		return new LinkedHashSet<>(Arrays.asList(this.controllers));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
public class Book {
 | 
			
		||||
 | 
			
		||||
	String id;
 | 
			
		||||
 | 
			
		||||
	String name;
 | 
			
		||||
 | 
			
		||||
	int pageCount;
 | 
			
		||||
 | 
			
		||||
	String author;
 | 
			
		||||
 | 
			
		||||
	public Book() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Book(String id, String name, int pageCount, String author) {
 | 
			
		||||
		this.id = id;
 | 
			
		||||
		this.name = name;
 | 
			
		||||
		this.pageCount = pageCount;
 | 
			
		||||
		this.author = author;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getId() {
 | 
			
		||||
		return this.id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setId(String id) {
 | 
			
		||||
		this.id = id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getName() {
 | 
			
		||||
		return this.name;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setName(String name) {
 | 
			
		||||
		this.name = name;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getPageCount() {
 | 
			
		||||
		return this.pageCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setPageCount(int pageCount) {
 | 
			
		||||
		this.pageCount = pageCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getAuthor() {
 | 
			
		||||
		return this.author;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setAuthor(String author) {
 | 
			
		||||
		this.author = author;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import org.springframework.graphql.data.method.annotation.Argument;
 | 
			
		||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Example {@code @Controller} to be tested with {@link GraphQlTest @GraphQlTest}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 */
 | 
			
		||||
@Controller
 | 
			
		||||
public class BookController {
 | 
			
		||||
 | 
			
		||||
	@QueryMapping
 | 
			
		||||
	public Book bookById(@Argument String id) {
 | 
			
		||||
		return new Book("42", "Sample Book", 100, "Jane Spring");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Example {@link SpringBootApplication @SpringBootApplication} used with
 | 
			
		||||
 * {@link GraphQlTest @GraphQlTest} tests.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 */
 | 
			
		||||
@SpringBootApplication
 | 
			
		||||
public class ExampleGraphQlApplication {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.graphql.test.tester.GraphQlTester;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Integration test for {@link GraphQlTest @GraphQlTest} annotated tests.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 */
 | 
			
		||||
@GraphQlTest(BookController.class)
 | 
			
		||||
public class GraphQlTestIntegrationTest {
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private GraphQlTester graphQlTester;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void getBookdByIdShouldReturnTestBook() {
 | 
			
		||||
		String query = "{ bookById(id: \"book-1\"){ id name pageCount author } }";
 | 
			
		||||
		this.graphQlTester.query(query).execute().path("data.bookById.id").entity(String.class).isEqualTo("42");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,184 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.test.autoconfigure.graphql;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.module.SimpleModule;
 | 
			
		||||
import graphql.schema.idl.RuntimeWiring;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
 | 
			
		||||
import org.springframework.context.annotation.ComponentScan;
 | 
			
		||||
import org.springframework.context.annotation.FilterType;
 | 
			
		||||
import org.springframework.core.type.classreading.MetadataReader;
 | 
			
		||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
 | 
			
		||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
 | 
			
		||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
 | 
			
		||||
import org.springframework.graphql.web.WebInput;
 | 
			
		||||
import org.springframework.graphql.web.WebInterceptor;
 | 
			
		||||
import org.springframework.graphql.web.WebInterceptorChain;
 | 
			
		||||
import org.springframework.graphql.web.WebOutput;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for {@link GraphQlTypeExcludeFilter}
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 */
 | 
			
		||||
class GraphQlTypeExcludeFilterTests {
 | 
			
		||||
 | 
			
		||||
	private MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void matchWhenHasNoControllers() throws Exception {
 | 
			
		||||
		GraphQlTypeExcludeFilter filter = new GraphQlTypeExcludeFilter(WithNoControllers.class);
 | 
			
		||||
		assertThat(excludes(filter, Controller1.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, Controller2.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRuntimeWiringConfigurer.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleService.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRepository.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleWebInterceptor.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleModule.class)).isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void matchWhenHasController() throws Exception {
 | 
			
		||||
		GraphQlTypeExcludeFilter filter = new GraphQlTypeExcludeFilter(WithController.class);
 | 
			
		||||
		assertThat(excludes(filter, Controller1.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, Controller2.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRuntimeWiringConfigurer.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleService.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRepository.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleWebInterceptor.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleModule.class)).isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void matchNotUsingDefaultFilters() throws Exception {
 | 
			
		||||
		GraphQlTypeExcludeFilter filter = new GraphQlTypeExcludeFilter(NotUsingDefaultFilters.class);
 | 
			
		||||
		assertThat(excludes(filter, Controller1.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, Controller2.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRuntimeWiringConfigurer.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleService.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRepository.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleWebInterceptor.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleModule.class)).isTrue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void matchWithIncludeFilter() throws Exception {
 | 
			
		||||
		GraphQlTypeExcludeFilter filter = new GraphQlTypeExcludeFilter(WithIncludeFilter.class);
 | 
			
		||||
		assertThat(excludes(filter, Controller1.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, Controller2.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRuntimeWiringConfigurer.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleService.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRepository.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleWebInterceptor.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleModule.class)).isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	void matchWithExcludeFilter() throws Exception {
 | 
			
		||||
		GraphQlTypeExcludeFilter filter = new GraphQlTypeExcludeFilter(WithExcludeFilter.class);
 | 
			
		||||
		assertThat(excludes(filter, Controller1.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, Controller2.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRuntimeWiringConfigurer.class)).isFalse();
 | 
			
		||||
		assertThat(excludes(filter, ExampleService.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleRepository.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleWebInterceptor.class)).isTrue();
 | 
			
		||||
		assertThat(excludes(filter, ExampleModule.class)).isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private boolean excludes(GraphQlTypeExcludeFilter filter, Class<?> type) throws IOException {
 | 
			
		||||
		MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(type.getName());
 | 
			
		||||
		return filter.match(metadataReader, this.metadataReaderFactory);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@GraphQlTest
 | 
			
		||||
	static class WithNoControllers {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@GraphQlTest(Controller1.class)
 | 
			
		||||
	static class WithController {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@GraphQlTest(useDefaultFilters = false)
 | 
			
		||||
	static class NotUsingDefaultFilters {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@GraphQlTest(includeFilters = @ComponentScan.Filter(Repository.class))
 | 
			
		||||
	static class WithIncludeFilter {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@GraphQlTest(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Controller1.class))
 | 
			
		||||
	static class WithExcludeFilter {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Controller
 | 
			
		||||
	static class Controller1 {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Controller
 | 
			
		||||
	static class Controller2 {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Service
 | 
			
		||||
	static class ExampleService {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Repository
 | 
			
		||||
	static class ExampleRepository {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class ExampleRuntimeWiringConfigurer implements RuntimeWiringConfigurer {
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void configure(RuntimeWiring.Builder builder) {
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class ExampleWebInterceptor implements WebInterceptor {
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Mono<WebOutput> intercept(WebInput webInput, WebInterceptorChain chain) {
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings("serial")
 | 
			
		||||
	static class ExampleModule extends SimpleModule {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
type Query {
 | 
			
		||||
    bookById(id: ID): Book
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Book {
 | 
			
		||||
    id: ID
 | 
			
		||||
    name: String
 | 
			
		||||
    pageCount: Int
 | 
			
		||||
    author: String
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue