Spring Boot 中 @RestClientTest 快速指南

更新于 2025-12-30

baeldung 2024-01-08

1. 简介

本文是对 @RestClientTest 注解的快速介绍。

这个新注解有助于简化并加速在 Spring 应用程序中对 REST 客户端的测试。

2. Spring Boot 1.4 之前的 REST 客户端支持

Spring Boot 是一个非常实用的框架,它提供了大量自动配置的 Spring Bean 和典型设置,让你可以将精力更多地集中在代码和业务逻辑上,而不是 Spring 应用的配置上。

但在 1.3 版本中,当你需要创建或测试 REST 服务客户端时,Spring Boot 并没有提供太多帮助。它对 REST 客户端的支持并不深入。

通常,我们会使用 RestTemplate 实例来创建 REST API 客户端。通常在使用前需要对其进行配置,而配置方式可能各不相同,因此 Spring Boot 并未提供一个通用配置好的 RestTemplate Bean。

REST 客户端的测试也是如此。在 Spring Boot 1.4.0 之前,测试 Spring REST 客户端的过程与任何其他基于 Spring 的应用程序并没有太大区别。你需要创建一个 MockRestServiceServer 实例,将其绑定到待测的 RestTemplate 实例,并为其提供模拟的响应,例如:

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer =
  MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess());

// 使用上述 RestTemplate 的测试代码 ...

mockServer.verify();

此外,你还必须初始化 Spring 容器,并确保只加载所需的组件,以加快上下文加载时间(从而加快测试执行速度)。

3. Spring Boot 1.4+ 中的新 REST 客户端特性

从 Spring Boot 1.4 开始,团队投入了大量精力来简化和加速 REST 客户端的创建与测试。

下面让我们看看这些新特性。

3.1. 将 Spring Boot 添加到你的项目中

首先,你需要确保你的项目使用的是 Spring Boot 1.4.x 或更高版本:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <relativePath/> <!-- 从仓库查找父项目 -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

最新版本信息可在此处查看。

3.2. RestTemplateBuilder

Spring Boot 引入了自动配置的 RestTemplateBuilder,用于简化 RestTemplate 的创建,同时也提供了配套的 @RestClientTest 注解,用于测试通过 RestTemplateBuilder 构建的客户端。以下是如何使用自动注入的 RestTemplateBuilder 创建一个简单的 REST 客户端:

@Service
public class DetailsServiceClient {

    private final RestTemplate restTemplate;

    public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    public Details getUserDetails(String name) {
        return restTemplate.getForObject("/{name}/details",
          Details.class, name);
    }
}

注意:我们并未显式地将 RestTemplateBuilder 实例注入构造函数。这得益于 Spring 的一项新特性——隐式构造函数注入(implicit constructor injection)。

RestTemplateBuilder 提供了便捷方法,用于注册消息转换器、错误处理器、URI 模板处理器、基本认证,以及应用任何你所需的自定义配置。

3.3. @RestClientTest

要测试通过 RestTemplateBuilder 构建的 REST 客户端,你可以使用带有 @RestClientTest 注解的测试类,并配合 SpringRunner 执行。该注解会禁用完整的自动配置,仅应用与 REST 客户端测试相关的配置,例如 Jackson 或 GSON 自动配置以及 @JsonComponent Bean,但不会加载普通的 @Component Bean。

@RestClientTest 确保 Jackson 和 GSON 支持被自动配置,并向上下文中添加预配置好的 RestTemplateBuilderMockRestServiceServer 实例。待测的 Bean 可通过 @RestClientTest 注解的 valuecomponents 属性指定:

@RunWith(SpringRunner.class)
@RestClientTest(DetailsServiceClient.class)
public class DetailsServiceClientTest {

    @Autowired
    private DetailsServiceClient client;

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() throws Exception {
        String detailsString = 
          objectMapper.writeValueAsString(new Details("John Smith", "john"));
        
        this.server.expect(requestTo("/john/details"))
          .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));
    }

    @Test
    public void whenCallingGetUserDetails_thenClientMakesCorrectCall() 
      throws Exception {

        Details details = this.client.getUserDetails("john");

        assertThat(details.getLogin()).isEqualTo("john");
        assertThat(details.getName()).isEqualTo("John Smith");
    }
}

首先,我们需要通过添加 @RunWith(SpringRunner.class) 注解,确保该测试由 SpringRunner 执行。

那么,有什么新变化呢?

第一,@RestClientTest 注解允许我们明确指定待测的服务类——在本例中是 DetailsServiceClient。该服务会被加载到测试上下文中,而其他组件则被过滤掉。

这使我们可以在测试中自动装配 DetailsServiceClient 实例,同时排除其他不必要的 Bean,从而加快上下文加载速度。

第二,对于使用 @RestClientTest 注解的测试,MockRestServiceServer 实例也会被自动配置(并为我们绑定到 DetailsServiceClient 实例),因此我们可以直接注入并使用它。

第三,@RestClientTest 提供了 JSON 支持,允许我们注入 Jackson 的 ObjectMapper 实例,以便准备 MockRestServiceServer 的模拟响应内容。

剩下的工作就是调用我们的服务并验证结果即可。

4. 结论

在本文中,我们探讨了新的 @RestClientTest 注解,它使得使用 Spring 构建的 REST 客户端的测试变得简单而高效。