Our @SpringBootTest
in a SERVLET
SpringApplication fails with the stacktrace below after an upgrade from Spring-Boot 2.3.6 to 2.4.0.
It seems like a check on the presence of WebClient
had been removed with the refactoring at https://github.com/spring-projects/spring-boot/commit/6b437ece548802f0803f761f6b10acc9b560f571#diff-0468685a60929025a2cf3fe3ed6a01021f7b6865d562536897e5915c3a483c40L42.
This pull request adds the check for isWebClientPresent()
.
stacktrace
Error creating bean with name 'org.springframework.test.web.reactive.server.WebTestClient': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: No suitable default ClientHttpConnector found
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.test.web.reactive.server.WebTestClient': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: No suitable default ClientHttpConnector found
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1879)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1268)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:267)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1161)
at org.spockframework.spring.SpringMockTestExecutionListener.beforeTestMethod(SpringMockTestExecutionListener.java:79)
at org.spockframework.spring.AbstractSpringTestExecutionListener.beforeTestMethod(AbstractSpringTestExecutionListener.java:39)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:289)
at org.spockframework.spring.SpringTestContextManager.beforeTestMethod(SpringTestContextManager.java:60)
at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:50)
at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:30)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:97)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:119)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.IllegalStateException: No suitable default ClientHttpConnector found
at org.springframework.test.web.reactive.server.DefaultWebTestClientBuilder.initConnector(DefaultWebTestClientBuilder.java:295)
at org.springframework.test.web.reactive.server.DefaultWebTestClientBuilder.build(DefaultWebTestClientBuilder.java:266)
at org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer$WebTestClientFactory.createWebTestClient(WebTestClientContextCustomizer.java:162)
at org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer$WebTestClientFactory.getObject(WebTestClientContextCustomizer.java:150)
at org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer$WebTestClientFactory.getObject(WebTestClientContextCustomizer.java:126)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:169)
... 34 more
Comment From: gesellix
Please leave a note if you'd like to have a test case for the change.
Comment From: wilkinsona
Thanks very much for the pull request, @gesellix. A test for this would be great if you have the time. It should be possible to test it using @ClassPathExclusions
to exclude the spring-webflux
jar from the classpath and then verify that the factory does not produce a customizer.
Comment From: gesellix
@wilkinsona thanks for the hints about @ClassPathExclusions
, I've implemented both test cases in separate test classes. In other news: I found the checkstyle checks and especially the format
task very helpful!
Comment From: snicoll
@gesellix thank you for the report and the PR.
Comment From: gesellix
You're welcome, thanks for merging! :)