概述

本文简要介绍了@RestClientTest注解在Spring应用程序中简化和加速REST客户端测试的功能。

Spring Boot框架提供了一系列自动配置的Spring Bean,它们具有典型的设置,这使得开发者可以将更多精力放在代码和业务逻辑上,而无需过多关注Spring应用的配置。

但在Spring Boot 1.4之前,对于创建或测试REST服务客户端,我们并没有得到太多帮助。其对REST客户端的支持相对较浅。

通常,为了访问REST API,我们会使用RestTemplate实例。然而,它在使用前通常需要配置,并且配置可能因场景而异,因此Spring Boot并未提供一个全局配置的RestTemplate Bean。

同样,在Spring Boot 1.4.0之前,测试REST客户端的过程与其他基于Spring的应用程序差别不大。你需要创建一个MockRestServiceServer实例,将其绑定到待测试的RestTemplate,并为其提供请求的模拟响应:

RestTemplate restTemplate = new RestTemplate();

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

// Test code that uses the above 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/> <!-- lookup parent from repository -->
</parent>

最新版本可在这里找到。

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的一个新特性——隐式构造函数注入,详细内容请参阅这篇文章

RestTemplateBuilder提供了方便的方法,用于注册消息转换器、错误处理器、URI模板处理器、基本授权,以及添加任何额外自定义配置。

3.3. @RestClientTest

对于使用RestTemplateBuilder构建的REST客户端进行测试,你可以使用SpringRunner执行的带有@RestClientTest注解的测试类。此注解会禁用全面的自动配置,仅应用与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实例,而将其他东西保留在外部,从而加快上下文加载速度。

其次,由于MockRestServiceServer实例在@RestClientTest注解的测试中也被配置好,并自动绑定到DetailsServiceClient实例,我们可以直接注入并使用它。

最后@RestClientTest的JSON支持允许我们将Jackson的ObjectMapper实例注入到MockRestServiceServer的模拟答案值中。

剩下的就是执行服务调用并验证结果。

4. 总结

本文讨论了新的@RestClientTest注解,它使得在Spring中轻松快速地测试构建的REST客户端成为可能。

本文的源代码可在GitHub上获取。


« 上一篇: Spring MVC与Velocity
» 下一篇: JMockit期望指南