EDIT: This question specifically refers to the @RestClientTest annotation introduced in spring-boot 1.4.0, which is intended to replace the factory method.
Problem:
According to the documentation, @RestClientTest should properly configure the MockRestServiceServer to use when testing the REST client. However, when I run the test, I get an IllegalStateException exception that indicates that the MockServerRestTemplateCustomizer is not bound to the RestTemplate.
It is worth noting that I use Gson for deserialization, not for Jackson, so an exception.
Does anyone know how to properly use this new annotation? I did not find examples requiring more configuration, and then when I already have it.
Configuration:
@SpringBootConfiguration @ComponentScan @EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class}) public class ClientConfiguration { ... @Bean public RestTemplateBuilder restTemplateBuilder() { return new RestTemplateBuilder() .rootUri(rootUri) .basicAuthorization(username, password); } }
Customer:
@Service public class ComponentsClientImpl implements ComponentsClient { private RestTemplate restTemplate; @Autowired public ComponentsClientImpl(RestTemplateBuilder builder) { this.restTemplate = builder.build(); } public ResponseDTO getComponentDetails(RequestDTO requestDTO) { HttpEntity<RequestDTO> entity = new HttpEntity<>(requestDTO); ResponseEntity<ResponseDTO> response = restTemplate.postForEntity("/api", entity, ResponseDTO.class); return response.getBody(); } }
Test
@RunWith(SpringRunner.class) @RestClientTest(ComponentsClientImpl.class) public class ComponentsClientTest { @Autowired private ComponentsClient client; @Autowired private MockRestServiceServer server; @Test public void getComponentDetailsWhenResultIsSuccessShouldReturnComponentDetails() throws Exception { server.expect(requestTo("/api")) .andRespond(withSuccess(getResponseJson(), APPLICATION_JSON)); ResponseDTO response = client.getComponentDetails(requestDto); ResponseDTO expected = responseFromJson(getResponseJson()); assertThat(response, is(expectedResponse)); } }
And an exception:
java.lang.IllegalStateException: Unable to use auto-configured MockRestServiceServer since MockServerRestTemplateCustomizer has not been bound to a RestTemplate
Answer:
As per the answer below, there is no need to declare a RestTemplateBuilder bean in context, as it is already provided by the automatic spring-boot configuration.
If the project is a spring-boot application (it has the @SpringBootApplication annotation), this will work as intended. However, in the aforementioned case, the project was a client library and, therefore, did not have a main application.
To ensure that the RestTemplateBuilder has been correctly entered into the main application context (the bean has been removed), a CUSTOM filter (the one used by @SpringBootApplication) is required to check the components
@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class) })