异步请求
本节展示了如何单独使用 MockMvc 来测试异步请求处理。
如果通过 WebTestClient 使用 MockMvc,则无需做任何特殊处理即可使
异步请求工作,因为 WebTestClient
会自动执行本节中描述的操作。
Servlet 异步请求(Spring MVC 中支持)的工作原理是退出 Servlet 容器线程,并允许应用程序异步计算 响应,之后进行异步调度以在 Servlet 容器线程上完成处理。
在 Spring MVC Test 中,可以通过首先断言生成的异步值,然后手动执行异步调度,最后验证响应来测试异步请求。
下面是一个针对返回 DeferredResult
、Callable
或 Reactor Mono
等响应式类型的控制器方法的示例测试:
- Java
-
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.* @Test void test() throws Exception { MvcResult mvcResult = this.mockMvc.perform(get("/path")) .andExpect(status().isOk()) [id="CO1-1"]1 .andExpect(request().asyncStarted()) [id="CO1-2"]2 .andExpect(request().asyncResult("body")) [id="CO1-3"]3 .andReturn(); this.mockMvc.perform(asyncDispatch(mvcResult)) [id="CO1-4"]4 .andExpect(status().isOk()) [id="CO1-5"]5 .andExpect(content().string("body")); }
<1> 检查响应状态是否未改变 <1> 异步处理必须已开始 <1> 等待并断言异步结果 <1> 手动执行 ASYNC 调度(因为没有正在运行的容器) <1> 验证最终响应
- Kotlin
-
@Test fun test() { var mvcResult = mockMvc.get("/path").andExpect { status { isOk() } [id="CO2-1"][id="CO1-1"][id="CO2-1"](1) request { asyncStarted() } [id="CO2-2"][id="CO1-2"][id="CO2-2"](2) // TODO Remove unused generic parameter request { asyncResult<Nothing>("body") } [id="CO2-3"][id="CO1-3"][id="CO2-3"](3) }.andReturn() mockMvc.perform(asyncDispatch(mvcResult)) [id="CO2-4"][id="CO1-4"][id="CO2-4"](4) .andExpect { status { isOk() } [id="CO2-5"][id="CO1-5"][id="CO2-5"](5) content().string("body") } }
<1> 检查响应状态是否未改变 <1> 异步处理必须已开始 <1> 等待并断言异步结果 <1> 手动执行 ASYNC 调度(因为没有正在运行的容器) <1> 验证最终响应