Reputation: 1090
I am using spring boot 1.5.8 and want to test my client:
@Component
public class RestClientBean implements RestClient {
private Map<String, RestTemplate> restTemplates = new HashMap<>();
@Autowired
public RestClientBean(RestTemplateBuilder builder, SomeConfig conf) {
restTemplates.put("first", builder.rootUri("first").build();
restTemplates.put("second", builder.rootUri("second").build();
}
}
with the following test:
@RunWith(SpringRunner.class)
@RestClientTest(RestClient.class)
public class RestClientTest {
@Autowired
private RestClient client;
@Autowired
private MockRestServiceServer server;
@TestConfiguration
static class SomeConfigFooBarBuzz {
@Bean
public SomeConfig provideConfig() {
return new SomeConfig(); // btw. not sure why this works,
// but this is the only way
// I got rid of the "unable to load
// SomeConfig auto-wire" or something like this :)
// Anyway not my main issue
// EDIT: just realized that the whole
// @TestConfiguration part can be avoided by
// adding SomeConfig.class to the classes in the
// @RestClientTest annotation
}
}
@Before
public void setUp() throws Exception {
server.expect(requestTo("/somePath")) // here an exception is thrown
// (main issue)
.andRespond(withSuccess("<valid json>", MediaType.APPLICATION_JSON));
}
}
The exception is very clear:
java.lang.IllegalStateException: Unable to use auto-configured
MockRestServiceServer since MockServerRestTemplateCustomizer has been bound to
more than one RestTemplate
But is it somehow possible to get this tested or is it not allowed to instantiate two different rest templates in one client class? I have just the need to use the first rest template in some cases and the second one in some others.
Upvotes: 9
Views: 10707
Reputation: 1090
After some days of investigation and communication with spring folks via GitHub I found a solution for me and not receiving an answer here means my solution might be valuable for someone:
@RunWith(SpringRunner.class)
@RestClientTest(RestClient.class)
public class RestClientTest {
@Autowired
private RestClient client;
private MockRestServiceServer firstServer;
private MockRestServiceServer secondServer;
private static MockServerRestTemplateCustomizer customizer;
@TestConfiguration
static class RestTemplateBuilderProvider {
@Bean
public RestTemplateBuilder provideBuilder() {
customizer = new MockServerRestTemplateCustomizer();
return new RestTemplateBuilder(customizer);
}
}
@Before
public void setUp() {
Map<RestTemplate, MockRestServiceServer> servers = customizer.getServers();
// iterate and assign the mock servers according to your own strategy logic
}
@Test
public void someTest() {
firstServer.expect(requestTo("/somePath"))
.andRespond(withSuccess("some json body"),
MediaType.APPLICATION_JSON));
// call client
// verify response
}
Basically specify a number of mock servers same as the number of rest templates you use in your client code, then specify a test configuration providing a rest builder with a customizer, so that your client code's rest templates will be built via this customized builder. Then use the customizer to get the mock servers bounded to the created rest templates and define expectations on them as you want.
Upvotes: 11