Async Requests

本节展示了如何独立使用 MockMvc 来测试异步请求处理。如果通过 WebTestClient使用 MockMvc,无需采取任何特殊操作便可让异步请求正常工作,因为 `WebTestClient`会自动完成本节所述的操作。

Servlet 异步请求(supported in Spring MVC)通过退出 Servlet 容器线程并允许应用程序异步计算响应进而发挥作用,在这一过程中,会进行异步调度以在 Servlet 容器线程上完成处理。

在 Spring MVC 测试中,可以通过断言生成的异步 value,然后手动执行异步分派,最后验证响应来测试异步请求。下面是一个 controller 方法的示例测试,这些方法返回 DeferredResultCallable 或反应式类型,如 Reactor Mono

Java
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*

@Test
void test() throws Exception {
       MvcResult mvcResult = this.mockMvc.perform(get("/path"))
               .andExpect(status().isOk()) 1
               .andExpect(request().asyncStarted()) 2
               .andExpect(request().asyncResult("body")) 3
               .andReturn();

       this.mockMvc.perform(asyncDispatch(mvcResult)) 4
               .andExpect(status().isOk()) 5
               .andExpect(content().string("body"));
   }
1 检查响应状态是否仍然不变
2 必须已经开始异步处理
3 等待并断言异步结果
4 手动执行一次 ASYNC 调度(因为没有运行容器)
5 Verify the final response
Kotlin
@Test
fun test() {
	var mvcResult = mockMvc.get("/path").andExpect {
		status { isOk() } (1)
		request { asyncStarted() } (2)
		// TODO Remove unused generic parameter
		request { asyncResult<Nothing>("body") } (3)
	}.andReturn()


	mockMvc.perform(asyncDispatch(mvcResult)) (4)
			.andExpect {
				status { isOk() } (5)
				content().string("body")
			}
}
6 检查响应状态是否仍然不变
7 必须已经开始异步处理
8 等待并断言异步结果
9 手动执行一次 ASYNC 调度(因为没有运行容器)
10 Verify the final response