Async Requests

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

This section shows how to use MockMvc on its own to test asynchronous request handling. If using MockMvc through the WebTestClient, there is nothing special to do to make asynchronous requests work as the WebTestClient automatically does what is described in this section.

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

Servlet asynchronous requests, supported in Spring MVC, work by exiting the Servlet container thread and allowing the application to compute the response asynchronously, after which an async dispatch is made to complete processing on a Servlet container thread.

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

In Spring MVC Test, async requests can be tested by asserting the produced async value first, then manually performing the async dispatch, and finally verifying the response. Below is an example test for controller methods that return DeferredResult, Callable, or reactive type such as 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 Check response status is still unchanged
2 Async processing must have started
3 Wait and assert the async result
4 Manually perform an ASYNC dispatch (as there is no running container)
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 Check response status is still unchanged
7 Async processing must have started
8 Wait and assert the async result
9 Manually perform an ASYNC dispatch (as there is no running container)
10 Verify the final response