Skip to content

GraphQlTester loading query from file conflicting with Boot autoconfiguration for graphql schemas #308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JimHosken opened this issue Feb 23, 2022 · 3 comments
Assignees
Labels
status: superseded Issue is superseded by another type: enhancement A general enhancement

Comments

@JimHosken
Copy link

spring-boot-starter-parent 2.7.0-M1 (spring-graphql 1.0.0-M5, spring-graphql-test 1.0.0-M5)

I have one schema file defined at src/main/resources/graphql/service.graphqls

For testing, I tried to define my graph QL queries in a file and reference them using the GraphQlTester.queryName functionality.

If I add a graphql file containing a query @ src/test/resources/graphql/fetchAllNotes.graphql, which is the default location that the GraphQlTestBuilderSupport.QueryNameResolver looks at, then the application fails to start because it cannot find the main schema definition file (src/main/resources/graphql/service.graphqls):

java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
	at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.postProcessFields(MockitoTestExecutionListener.java:110)
	at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.injectFields(MockitoTestExecutionListener.java:94)
	at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.prepareTestInstance(MockitoTestExecutionListener.java:61)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQlSource' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.graphql.execution.GraphQlSource]: Factory method 'graphQlSource' threw exception; nested exception is org.springframework.boot.autoconfigure.graphql.InvalidSchemaLocationsException: No schema file could be found in the provided locations.; nested exception is org.springframework.graphql.execution.MissingSchemaException: No GraphQL schema definition was configured.
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:719)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:401)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:124)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 28 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.graphql.execution.GraphQlSource]: Factory method 'graphQlSource' threw exception; nested exception is org.springframework.boot.autoconfigure.graphql.InvalidSchemaLocationsException: No schema file could be found in the provided locations.; nested exception is org.springframework.graphql.execution.MissingSchemaException: No GraphQL schema definition was configured.
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
	... 46 more
Caused by: org.springframework.boot.autoconfigure.graphql.InvalidSchemaLocationsException: No schema file could be found in the provided locations.; nested exception is org.springframework.graphql.execution.MissingSchemaException: No GraphQL schema definition was configured.
	at org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration.graphQlSource(GraphQlAutoConfiguration.java:91)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 47 more
Caused by: org.springframework.graphql.execution.MissingSchemaException: No GraphQL schema definition was configured.
	at java.util.Optional.orElseThrow(Optional.java:290)
	at org.springframework.graphql.execution.DefaultGraphQlSourceBuilder.build(DefaultGraphQlSourceBuilder.java:134)
	at org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration.graphQlSource(GraphQlAutoConfiguration.java:88)
	... 52 more
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 23, 2022
@bclozel bclozel self-assigned this Mar 3, 2022
@bclozel
Copy link
Member

bclozel commented Mar 3, 2022

Adding test query files means that two folder exist for the same classpath location classpath:graphql/:

  • src/main/resources/graphql/
  • src/test/resources/graphql/

When running tests, the test location is listed before the main one in the classpath. Because the Spring Boot auto-configuration looks for the classpath:graphql/**/ location by default, src/test/resources/graphql/ is found but doesn't hold any schema file. The startup fails as a result.

I think we discussed that already @rstoyanchev but I don't remember why we didn't settle for spring.graphql.schema.locations=classpath*:graphql/**/ as a default value to solve this. Maybe the classpath* scheme is a bit suboptimal or can be confusing for developers? Should we consider a different arrangement on the tester side?

@JimHosken you can use this value in your application.properties to work around this problem for now - the classpath* scheme means that we scan multiple locations matching the location pattern.

@JimHosken
Copy link
Author

@bclozel

Adding that configuration property fixed the issue. For reference, I added it to application.yml in src/test/resources. Then I was able to use GraphQlTester.queryName() and store my test queries in src/test/resources/graphql

@rstoyanchev rstoyanchev added this to the 1.0.0-RC1 milestone Mar 24, 2022
@rstoyanchev rstoyanchev added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 24, 2022
@rstoyanchev
Copy link
Contributor

The changes for #338 should make this a non-issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded Issue is superseded by another type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants