Refine GraphQL server auto-configuration
Prior to this commit, launching a GraphQL application without any schema file or customizer bean would result in an exception caught by a FailureAnalyzer telling the developer about configured locations. Since then, a new client has been introduced in Spring GraphQL and the mere presence of the GraphQL starter does not mean anymore that the intent is to create a GraphQL API in the app: we could instead just consume an existing, remote API. This commit refines the GraphQL server auto-configuration so that it is enabled only if: * there is at least one schema file in the configured locations * or a `GraphQlSourceCustomizer` bean has been defined in the app These changes make the custom FailureAnalyzer useless and is also removed as part of this commit. Closes gh-30035pull/30406/head
parent
bf79d6baef
commit
087e853c5d
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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 java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Conditional @Conditional} that only matches when a GraphQL schema is defined for
|
||||||
|
* the application, via schema files or infrastructure beans.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @since 2.7.0
|
||||||
|
*/
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Conditional(DefaultGraphQlSchemaCondition.class)
|
||||||
|
public @interface ConditionalOnGraphQlSchema {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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 java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.context.annotation.Condition;
|
||||||
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
|
import org.springframework.context.annotation.ConfigurationCondition;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||||
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Condition} that checks whether a GraphQL schema has been defined in the
|
||||||
|
* application. This is looking for:
|
||||||
|
* <ul>
|
||||||
|
* <li>schema files in the {@link GraphQlProperties configured locations}</li>
|
||||||
|
* <li>or infrastructure beans such as {@link GraphQlSourceBuilderCustomizer}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @see ConditionalOnGraphQlSchema
|
||||||
|
*/
|
||||||
|
class DefaultGraphQlSchemaCondition extends SpringBootCondition implements ConfigurationCondition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigurationCondition.ConfigurationPhase getConfigurationPhase() {
|
||||||
|
return ConfigurationCondition.ConfigurationPhase.REGISTER_BEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||||
|
boolean match = false;
|
||||||
|
List<ConditionMessage> messages = new ArrayList<>(2);
|
||||||
|
ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnGraphQlSchema.class);
|
||||||
|
|
||||||
|
Binder binder = Binder.get(context.getEnvironment());
|
||||||
|
GraphQlProperties.Schema schema = binder.bind("spring.graphql.schema", GraphQlProperties.Schema.class)
|
||||||
|
.orElse(new GraphQlProperties.Schema());
|
||||||
|
ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils
|
||||||
|
.getResourcePatternResolver(context.getResourceLoader());
|
||||||
|
List<Resource> schemaResources = resolveSchemaResources(resourcePatternResolver, schema.getLocations(),
|
||||||
|
schema.getFileExtensions());
|
||||||
|
if (!schemaResources.isEmpty()) {
|
||||||
|
match = true;
|
||||||
|
messages.add(message.found("schema", "schemas").items(ConditionMessage.Style.QUOTE, schemaResources));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messages.add(message.didNotFind("schema files in locations").items(ConditionMessage.Style.QUOTE,
|
||||||
|
Arrays.asList(schema.getLocations())));
|
||||||
|
}
|
||||||
|
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||||
|
String[] customizerBeans = beanFactory.getBeanNamesForType(GraphQlSourceBuilderCustomizer.class, false, false);
|
||||||
|
if (customizerBeans.length != 0) {
|
||||||
|
match = true;
|
||||||
|
messages.add(message.found("customizer", "customizers").items(Arrays.asList(customizerBeans)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messages.add((message.didNotFind("GraphQlSourceBuilderCustomizer").atAll()));
|
||||||
|
}
|
||||||
|
return new ConditionOutcome(match, ConditionMessage.of(messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, String[] locations,
|
||||||
|
String[] extensions) {
|
||||||
|
List<Resource> resources = new ArrayList<>();
|
||||||
|
for (String location : locations) {
|
||||||
|
for (String extension : extensions) {
|
||||||
|
resources.addAll(resolveSchemaResources(resolver, location + "*" + extension));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, String pattern) {
|
||||||
|
try {
|
||||||
|
return Arrays.asList(resolver.getResources(pattern));
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.autoconfigure.graphql;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.core.NestedRuntimeException;
|
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link InvalidSchemaLocationsException} thrown when no schema file could be found in
|
|
||||||
* the provided locations.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.7.0
|
|
||||||
*/
|
|
||||||
public class InvalidSchemaLocationsException extends NestedRuntimeException {
|
|
||||||
|
|
||||||
private final List<SchemaLocation> schemaLocations;
|
|
||||||
|
|
||||||
public InvalidSchemaLocationsException(String[] locations, ResourcePatternResolver resolver) {
|
|
||||||
this(locations, resolver, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InvalidSchemaLocationsException(String[] locations, ResourcePatternResolver resolver, Throwable cause) {
|
|
||||||
super("No schema file could be found in the provided locations.", cause);
|
|
||||||
Assert.notEmpty(locations, "locations should not be empty");
|
|
||||||
Assert.notNull(resolver, "resolver should not be null");
|
|
||||||
List<SchemaLocation> providedLocations = new ArrayList<>();
|
|
||||||
for (String location : locations) {
|
|
||||||
try {
|
|
||||||
String uri = resolver.getResource(location).getURI().toASCIIString();
|
|
||||||
providedLocations.add(new SchemaLocation(location, uri));
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
providedLocations.add(new SchemaLocation(location, ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.schemaLocations = Collections.unmodifiableList(providedLocations);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the list of provided locations where to look for schemas.
|
|
||||||
* @return the list of locations
|
|
||||||
*/
|
|
||||||
public List<SchemaLocation> getSchemaLocations() {
|
|
||||||
return this.schemaLocations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The location where to look for schemas.
|
|
||||||
*/
|
|
||||||
public static class SchemaLocation {
|
|
||||||
|
|
||||||
private final String location;
|
|
||||||
|
|
||||||
private final String uri;
|
|
||||||
|
|
||||||
SchemaLocation(String location, String uri) {
|
|
||||||
this.location = location;
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the location String to be resolved by a {@link ResourcePatternResolver}.
|
|
||||||
* @return the location
|
|
||||||
*/
|
|
||||||
public String getLocation() {
|
|
||||||
return this.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the resolved URI String for this location, an empty String if resolution
|
|
||||||
* failed.
|
|
||||||
* @return the resolved location or an empty String
|
|
||||||
*/
|
|
||||||
public String getUri() {
|
|
||||||
return this.uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
|
||||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link AbstractFailureAnalyzer} to analyze failures caused by
|
|
||||||
* {@link InvalidSchemaLocationsException}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class InvalidSchemaLocationsExceptionFailureAnalyzer extends AbstractFailureAnalyzer<InvalidSchemaLocationsException> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FailureAnalysis analyze(Throwable rootFailure, InvalidSchemaLocationsException cause) {
|
|
||||||
String message = "Could not find any GraphQL schema file under configured locations.";
|
|
||||||
StringBuilder action = new StringBuilder(
|
|
||||||
"Check that the following locations contain schema files: " + System.lineSeparator());
|
|
||||||
for (InvalidSchemaLocationsException.SchemaLocation schemaLocation : cause.getSchemaLocations()) {
|
|
||||||
action.append(String.format("- '%s' (%s)" + System.lineSeparator(), schemaLocation.getUri(),
|
|
||||||
schemaLocation.getLocation()));
|
|
||||||
}
|
|
||||||
return new FailureAnalysis(message, action.toString(), cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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 java.util.Collection;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
||||||
|
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ConditionalOnGraphQlSchema}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class DefaultGraphQlSchemaConditionTests {
|
||||||
|
|
||||||
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matchesWhenSchemaFilesAreDetected() {
|
||||||
|
this.contextRunner.withUserConfiguration(TestingConfiguration.class).run((context) -> {
|
||||||
|
didMatch(context);
|
||||||
|
assertThat(conditionReportMessage(context)).contains("@ConditionalOnGraphQlSchema found schemas")
|
||||||
|
.contains("@ConditionalOnGraphQlSchema did not find GraphQlSourceBuilderCustomizer");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void matchesWhenCustomizerIsDetected() {
|
||||||
|
this.contextRunner.withUserConfiguration(CustomCustomizerConfiguration.class, TestingConfiguration.class)
|
||||||
|
.withPropertyValues("spring.graphql.schema.locations=classpath:graphql/missing").run((context) -> {
|
||||||
|
didMatch(context);
|
||||||
|
assertThat(conditionReportMessage(context)).contains(
|
||||||
|
"@ConditionalOnGraphQlSchema did not find schema files in locations 'classpath:graphql/missing/'")
|
||||||
|
.contains("@ConditionalOnGraphQlSchema found customizer myBuilderCuystomizer");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void doesNotMatchWhenBothAreMissing() {
|
||||||
|
this.contextRunner.withUserConfiguration(TestingConfiguration.class)
|
||||||
|
.withPropertyValues("spring.graphql.schema.locations=classpath:graphql/missing").run((context) -> {
|
||||||
|
assertThat(context).doesNotHaveBean("success");
|
||||||
|
assertThat(conditionReportMessage(context)).contains(
|
||||||
|
"@ConditionalOnGraphQlSchema did not find schema files in locations 'classpath:graphql/missing/'")
|
||||||
|
.contains("@ConditionalOnGraphQlSchema did not find GraphQlSourceBuilderCustomizer");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void didMatch(AssertableApplicationContext context) {
|
||||||
|
assertThat(context).hasBean("success");
|
||||||
|
assertThat(context.getBean("success")).isEqualTo("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String conditionReportMessage(AssertableApplicationContext context) {
|
||||||
|
Collection<ConditionEvaluationReport.ConditionAndOutcomes> conditionAndOutcomes = ConditionEvaluationReport
|
||||||
|
.get(context.getSourceApplicationContext().getBeanFactory()).getConditionAndOutcomesBySource().values();
|
||||||
|
return conditionAndOutcomes.iterator().next().iterator().next().getOutcome().getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnGraphQlSchema
|
||||||
|
static class TestingConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
String success() {
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class CustomCustomizerConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
GraphQlSourceBuilderCustomizer myBuilderCuystomizer() {
|
||||||
|
return (builder) -> {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link InvalidSchemaLocationsExceptionFailureAnalyzer}
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class InvalidSchemaLocationsExceptionFailureAnalyzerTests {
|
|
||||||
|
|
||||||
private final InvalidSchemaLocationsExceptionFailureAnalyzer analyzer = new InvalidSchemaLocationsExceptionFailureAnalyzer();
|
|
||||||
|
|
||||||
private final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
|
||||||
|
|
||||||
private final String[] missingLocation = new String[] {
|
|
||||||
"classpath:org/springframework/boot/autoconfigure/graphql/missing/" };
|
|
||||||
|
|
||||||
private final String[] existingLocation = new String[] {
|
|
||||||
"classpath:org/springframework/boot/autoconfigure/graphql/" };
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldReportCause() {
|
|
||||||
InvalidSchemaLocationsException exception = new InvalidSchemaLocationsException(this.existingLocation,
|
|
||||||
this.resolver);
|
|
||||||
FailureAnalysis analysis = this.analyzer.analyze(exception);
|
|
||||||
assertThat(analysis.getCause()).isInstanceOf(InvalidSchemaLocationsException.class);
|
|
||||||
assertThat(analysis.getAction()).contains("Check that the following locations contain schema files:");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldListUnresolvableLocation() {
|
|
||||||
InvalidSchemaLocationsException exception = new InvalidSchemaLocationsException(this.missingLocation,
|
|
||||||
this.resolver);
|
|
||||||
FailureAnalysis analysis = this.analyzer.analyze(exception);
|
|
||||||
assertThat(analysis.getAction()).contains(this.existingLocation[0]).doesNotContain("file:");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldListExistingLocation() {
|
|
||||||
InvalidSchemaLocationsException exception = new InvalidSchemaLocationsException(this.existingLocation,
|
|
||||||
this.resolver);
|
|
||||||
FailureAnalysis analysis = this.analyzer.analyze(exception);
|
|
||||||
assertThat(analysis.getAction()).contains(this.existingLocation[0]).contains("file:");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link InvalidSchemaLocationsException}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class InvalidSchemaLocationsExceptionTests {
|
|
||||||
|
|
||||||
private final String schemaFolder = "graphql/";
|
|
||||||
|
|
||||||
private final String[] locations = new String[] { "classpath:" + this.schemaFolder };
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldRejectEmptyLocations() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(
|
|
||||||
() -> new InvalidSchemaLocationsException(new String[] {}, new PathMatchingResourcePatternResolver()))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class).withMessage("locations should not be empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldRejectNullResolver() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> new InvalidSchemaLocationsException(this.locations, null))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class).withMessage("resolver should not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldExposeConfiguredLocations() {
|
|
||||||
InvalidSchemaLocationsException exception = new InvalidSchemaLocationsException(this.locations,
|
|
||||||
new PathMatchingResourcePatternResolver());
|
|
||||||
assertThat(exception.getSchemaLocations()).hasSize(1);
|
|
||||||
InvalidSchemaLocationsException.SchemaLocation schemaLocation = exception.getSchemaLocations().get(0);
|
|
||||||
assertThat(schemaLocation.getLocation()).isEqualTo(this.locations[0]);
|
|
||||||
assertThat(schemaLocation.getUri()).endsWith(this.schemaFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldNotFailWithUnresolvableLocations() {
|
|
||||||
String unresolved = "classpath:unresolved/";
|
|
||||||
InvalidSchemaLocationsException exception = new InvalidSchemaLocationsException(new String[] { unresolved },
|
|
||||||
new PathMatchingResourcePatternResolver());
|
|
||||||
assertThat(exception.getSchemaLocations()).hasSize(1);
|
|
||||||
InvalidSchemaLocationsException.SchemaLocation schemaLocation = exception.getSchemaLocations().get(0);
|
|
||||||
assertThat(schemaLocation.getLocation()).isEqualTo(unresolved);
|
|
||||||
assertThat(schemaLocation.getUri()).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue