对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

测试客户端应用程序

您可以使用客户端测试来测试内部使用RestTemplate的代码。这个想法是声明预期的请求并提供“stub”响应,以便您可以专注于隔离测试代码(即,无需运行服务器)。以下示例展示了如何做到这一点:spring-doc.cadn.net.cn

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();
val restTemplate = RestTemplate()

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

// Test code that uses the above RestTemplate ...

mockServer.verify()

在前面的例子中,MockRestServiceServer(客户端 REST 测试的核心类)使用自定义的 ClientHttpRequestFactory 配置 RestTemplate,该 ClientHttpRequestFactory 断言实际请求与预期相符并返回“模拟”响应。在这种情况下,我们期望对 /greeting 的请求,并希望返回 200 响应和 text/plain 内容。我们可以根据需要定义额外的预期请求和模拟响应。当定义了预期请求和模拟响应后,RestTemplate 可以像往常一样在客户端代码中使用。mockServer.verify() 可用于验证所有预期是否已满足。spring-doc.cadn.net.cn

默认情况下,请求按预期声明的顺序接收。您可以在构建服务器时设置ignoreExpectOrder选项,在这种情况下,所有预期都会被检查(按顺序)以找到与给定请求的匹配项。这意味着请求可以按任何顺序到达。以下示例使用ignoreExpectOrderspring-doc.cadn.net.cn

server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build()

即使默认情况下请求是无序的,每个请求也只允许运行一次。 expect 方法提供了一个重载变体,接受一个 ExpectedCount 参数,该参数指定了计数范围(例如,oncemanyTimesmaxminbetween 等)。以下示例使用了 timesspring-doc.cadn.net.cn

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess());
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess());

// ...

mockServer.verify();
val restTemplate = RestTemplate()

val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess())
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess())

// ...

mockServer.verify()

请注意,当 ignoreExpectOrder 未设置(默认值)时,因此请求按声明顺序预期,则该顺序仅适用于任何预期请求中的第一个。例如,如果 "/something" 预期出现两次,然后 "/somewhere" 预期出现三次,则应先有一个请求到 "/something",然后再有一个请求到 "/somewhere",但除此之外,后续的 "/something" 和 "/somewhere" 请求可以在任何时候到达。spring-doc.cadn.net.cn

作为上述所有方法的替代方案,客户端测试支持还提供了一个ClientHttpRequestFactory实现,您可以将其配置到RestTemplate中,以绑定到MockMvc实例。这允许使用实际的服务器端逻辑处理请求,但无需运行服务器。以下示例展示了如何操作:spring-doc.cadn.net.cn

MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc));

// Test code that uses the above RestTemplate ...
val mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build()
restTemplate = RestTemplate(MockMvcClientHttpRequestFactory(mockMvc))

// Test code that uses the above RestTemplate ...

在某些情况下,可能需要实际调用远程服务而非模拟响应。以下示例展示了如何通过 ExecutingResponseCreator实现:spring-doc.cadn.net.cn

RestTemplate restTemplate = new RestTemplate();

// Create ExecutingResponseCreator with the original request factory
ExecutingResponseCreator withActualResponse = new ExecutingResponseCreator(restTemplate.getRequestFactory());

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

// Test code that uses the above RestTemplate ...

mockServer.verify();
val restTemplate = RestTemplate()

// Create ExecutingResponseCreator with the original request factory
val withActualResponse = new ExecutingResponseCreator(restTemplate.getRequestFactory())

val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(requestTo("/profile")).andRespond(withSuccess())
mockServer.expect(requestTo("/quoteOfTheDay")).andRespond(withActualResponse)

// Test code that uses the above RestTemplate ...

mockServer.verify()

在前述示例中,我们使用RestTemplate中的ClientHttpRequestFactory创建了ExecutingResponseCreatorMockRestServiceServer将其替换为模拟响应的不同实现之前。 随后我们定义了两种响应类型的预期:spring-doc.cadn.net.cn

在第二种情况下,请求通过先前捕获的ClientHttpRequestFactory执行。这会生成一个响应,例如可能来自实际的远程服务器,具体取决于RestTemplate的最初配置方式。spring-doc.cadn.net.cn

静态导入

与服务器端测试类似,客户端测试的流畅API也需要几个静态导入。通过搜索MockRest*可以很容易找到这些导入。Eclipse用户应该在Eclipse首选项中的Java → 编辑器 → 内容辅助 → 收藏夹下将MockRestRequestMatchers.*MockRestResponseCreators.*添加为“收藏静态成员”。这允许在输入静态方法名的第一个字符后使用内容辅助。其他IDE(如IntelliJ)可能不需要任何额外配置。检查对静态成员的代码补全支持。spring-doc.cadn.net.cn

客户端REST测试的更多示例

Spring MVC Test 自带的测试包括 示例测试 客户端 REST 测试。spring-doc.cadn.net.cn