Skip to content

Support RestClient.Builder with @RestClientTest #37033

Closed
@rwinch

Description

@rwinch

It is convenient that Spring Boot autoconfiguration supports creating a RestClient.Builder. However, it is not clear how to best use the RestClient.Builder when testing.

Boot provides @RestClientTest which makes it easier to test when using RestTemplateBuilder. However, at the moment (Spring Boot 3.2.0-M1) using RestClient.Builder with @RestClientTest produces the following error:

Failed to load ApplicationContext for [MergedContextConfiguration@abff8b7 testClass = example.RepositoryServiceTests, locations = [], classes = [example.Application], contextInitializerClasses = [], activeProfiles = [], propertySourceLocations = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.web.client.RestClientTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@27d4a09, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@9be1041, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@95d784df, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6436a7db, [ImportsContextCustomizer@6d7cada5 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.test.autoconfigure.web.client.WebClientRestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@16c63f5, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@b1712f3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@f946572c], contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
java.lang.IllegalStateException: Failed to load ApplicationContext for [MergedContextConfiguration@abff8b7 testClass = example.RepositoryServiceTests, locations = [], classes = [example.Application], contextInitializerClasses = [], activeProfiles = [], propertySourceLocations = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.web.client.RestClientTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@27d4a09, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@9be1041, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@95d784df, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6436a7db, [ImportsContextCustomizer@6d7cada5 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.test.autoconfigure.web.client.WebClientRestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@16c63f5, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@b1712f3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@f946572c], contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)
	...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'repositoryService' defined in class path resource [example/RepositoryServiceConfiguration.class]: Unsatisfied dependency expressed through method 'repositoryService' parameter 0: No qualifying bean of type 'org.springframework.web.client.RestClient$Builder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801)
	...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.web.client.RestClient$Builder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

If I try and @ImportAutoConfiguration(RestClientAutoConfiguration.class) I get the following error:

Unable to use auto-configured MockRestServiceServer since MockServerRestTemplateCustomizer has not been bound to a RestTemplate
java.lang.IllegalStateException: Unable to use auto-configured MockRestServiceServer since MockServerRestTemplateCustomizer has not been bound to a RestTemplate
	at org.springframework.util.Assert.state(Assert.java:76)
	at org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration$DeferredRequestExpectationManager.getDelegate(MockRestServiceServerAutoConfiguration.java:116)
	at org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration$DeferredRequestExpectationManager.expectRequest(MockRestServiceServerAutoConfiguration.java:88)
	at org.springframework.test.web.client.MockRestServiceServer.expect(MockRestServiceServer.java:108)
	at org.springframework.test.web.client.MockRestServiceServer.expect(MockRestServiceServer.java:93)
	at example.RepositoryServiceTests.getRepository(RepositoryServiceTests.java:26)
	...

I am able to work around it by using RestClient.builder(RestTemplateBuilder.build()) instead of the RestClient.Builder, but this seems to defeat the purpose of RestClient.Builder being provided by Boot's autoconfiguration.

It would be nice if there was a way I can use the autoconfigured RestClient.Builder in my tests.

You can find the last 3 commits in this branch demonstrate the various items I described https://github.com/rwinch/spring-security-sample/tree/boot-test-restclient

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions