测试客户端应用程序
您可以使用客户端测试来测试在内部使用 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
,该 ClientHttpRequestFactory
断言实际请求与预期相符,并返回“存根”响应。在这种情况下,我们希望请求 /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
参数,该参数指定一个计数范围(例如,once
、manyTimes
、max
、min
、between
等)。以下示例使用 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
之前使用 ClientHttpRequestFactory
创建了 ExecutingResponseCreator
。然后,我们使用两种类型的响应定义预期
-
200
响应存根用于/profile
端点(不会执行实际请求) -
通过调用
/quoteOfTheDay
端点获得的响应
在第二种情况下,请求通过先前捕获的 ClientHttpRequestFactory
执行。这会生成响应,例如,该响应可能来自实际远程服务器,具体取决于 RestTemplate
的原始配置方式。
静态导入
与服务器端测试一样,客户端测试的流畅 API 需要一些静态导入。通过搜索 MockRest*
可以轻松找到这些导入。Eclipse 用户应在 Eclipse 首选项中的 Java → 编辑器 → 内容辅助 → 收藏夹下将 MockRestRequestMatchers.*
和 MockRestResponseCreators.*
添加为“收藏的静态成员”。这允许在键入静态方法名称的第一个字符后使用内容辅助。其他 IDE(如 IntelliJ)可能不需要任何其他配置。检查对静态成员代码补全的支持。
客户端 REST 测试的更多示例
Spring MVC 测试自己的测试包括 客户端 REST 测试示例。