首页 > 解决方案 > 在 RestClientTest 中测试 Spring Boots 缓存行为

问题描述

我有以下情况:

服务调用某个休息端点来查询资源。这个查询的结果应该缓存一天,然后再重新查询。

为了验证这种行为,我编写了一个测试,它调用了 service 方法 2 次,并期望其余的服务实际上只被查询了一次。

下面是调用端点的类:

@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();
        }
    }
}

然后我们在这里进行这个测试:

@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();
    }
}

如您所见,我们调用了 fetchResource 方法两次。但是 server.verify 调用失败,因为还有两个请求发送到模拟服务器。

我认为 RestClientTest 使用我的 CachedResourceClient 在幕后做了一些与缓存设置方式冲突的事情。

因为如果我删除 RestClientTest-Annotation 并手动模拟 RestTemplateBuilder 和 RestTemplate 测试按预期工作。但是拥有一个服务器模拟比手动模拟使用的类要舒服一些。

设置有问题吗?

标签: javaspringspring-bootunit-testingspring-cache

解决方案


推荐阅读