I have the following scenario:
A Service calls some rest endpoint to query a resource. The result of this query should be cached for one day and then requeried.
To verify this behavior I wrote a test that calls the service method 2 times and expects that the rest service was actually only queried one time.
Here would be the class that calls the endpoint:
@EnableCaching
@Service
public class CachedResourceClient {
private final RestTemplate restTemplate;
public CachedResourceClient(@Value("${api.host}") String apiHost, RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder
.rootUri(apiHost)
.build();
}
@Cacheable("resource")
public Optional<Resource> fetchResource() {
try {
return Optional.of(restTemplate.getForObject("/resource", Resource.class));
} catch (HttpClientErrorException | HttpServerErrorException | UnknownHttpStatusCodeException e) {
// logging
return Optional.empty();
}
}
}
and then we have this test here:
@RestClientTest(CachedResourceClient.class)
public class CachedResourceClientTests {
@Autowired
private MockRestServiceServer server;
@Autowired
private CachedResourceClient cachedResourceClient;
@Test
public void fetchResource() throws JsonProcessingException {
server.expect(requestTo("/resource"))
.andRespond(withSuccess("{ resource: 'some' }", MediaType.APPLICATION_JSON));
cachedResourceClient.fetchResource();
cachedResourceClient.fetchResource();
server.verify();
}
}
As you can see, we're calling the fetchResource method two times. But the server.verify call fails, because there are also two requests sent to the mock server.
I think the RestClientTest does something behind the scene with my CachedResourceClient that conflicts with the way Caching is setup.
Because if I remove the RestClientTest-Annotation and manually mock the RestTemplateBuilder and the RestTemplate the tests work as expected. But having a server mock is a bit more comfortable than manually mocking the used classes.
Is there something wrong with the setup?