测试客户端应用程序

您可以使用客户端测试来测试内部使用RestTemplate的代码。其思想是声明预期的请求并提供“存根”响应,以便您可以专注于隔离测试代码(即,无需运行服务器)。以下示例演示了如何操作

  • Java

  • Kotlin

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,该工厂根据预期对实际请求进行断言并返回“存根”响应。在本例中,我们期望对/greeting的请求,并希望返回一个带有text/plain内容的200响应。我们可以根据需要定义其他预期的请求和存根响应。当我们定义预期的请求和存根响应时,RestTemplate可以像往常一样在客户端代码中使用。在测试结束时,可以使用mockServer.verify()来验证所有预期都已满足。

默认情况下,请求的顺序应与声明预期的顺序一致。在构建服务器时,您可以设置ignoreExpectOrder选项,在这种情况下,将检查所有预期(按顺序)以查找与给定请求匹配的项。这意味着请求可以按任何顺序到达。以下示例使用ignoreExpectOrder

  • Java

  • Kotlin

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

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

  • Java

  • Kotlin

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”,则在请求“/somewhere”之前应该有对“/something”的请求,但是,除此之外,“/something”和“/somewhere”的后续请求可以在任何时间到达。

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

  • Java

  • Kotlin

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实现这一点

  • Java

  • Kotlin

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()

在前面的示例中,我们在MockRestServiceServer用模拟响应替换它 *之前* 使用RestTemplate中的ClientHttpRequestFactory创建ExecutingResponseCreator。然后我们使用两种响应定义预期

  • /profile端点的存根200响应(不会执行实际请求)

  • 通过对/quoteOfTheDay端点进行调用获得的响应

在第二种情况下,请求是通过前面捕获的ClientHttpRequestFactory执行的。这会生成一个响应,例如,根据RestTemplate的原始配置方式,该响应可能来自实际的远程服务器。

静态导入

与服务器端测试一样,客户端测试的流畅API需要一些静态导入。可以通过搜索MockRest*轻松找到这些导入。Eclipse用户应在Eclipse首选项中的Java → 编辑器 → 内容辅助 → 收藏夹下添加MockRestRequestMatchers.*MockRestResponseCreators.*作为“收藏夹静态成员”。这允许在键入静态方法名称的第一个字符后使用内容辅助。其他IDE(例如IntelliJ)可能不需要任何额外配置。检查对静态成员代码完成的支持。

客户端REST测试的更多示例

Spring MVC Test自己的测试包括客户端REST测试示例