执行请求

本节介绍如何独立使用 MockMvc 执行请求和验证响应。如果通过WebTestClient使用 MockMvc,请改阅关于编写测试的相关章节。

要执行使用任何 HTTP 方法的请求,如下例所示

// static import of MockMvcRequestBuilders.*

mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));

您还可以执行文件上传请求,这些请求内部使用MockMultipartHttpServletRequest,因此不会实际解析 multipart 请求。相反,您必须将其设置如下例所示

mockMvc.perform(multipart("/doc").file("a1", "ABC".getBytes("UTF-8")));

您可以使用 URI 模板样式指定查询参数,如下例所示

mockMvc.perform(get("/hotels?thing={thing}", "somewhere"));

您还可以添加 Servlet 请求参数,这些参数表示查询参数或表单参数,如下例所示

mockMvc.perform(get("/hotels").param("thing", "somewhere"));

如果应用程序代码依赖于 Servlet 请求参数并且没有显式检查查询字符串(大多数情况下都是如此),那么您使用哪种选项并不重要。但是,请记住,通过 URI 模板提供的查询参数将被解码,而通过param(…​)方法提供的请求参数则需要预先解码。

在大多数情况下,最好将上下文路径和 Servlet 路径排除在请求 URI 之外。如果您必须使用完整的请求 URI 进行测试,请确保相应地设置contextPathservletPath,以便请求映射正常工作,如下例所示

mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main"))

在上一个示例中,为每个执行的请求设置contextPathservletPath将很麻烦。相反,您可以设置默认请求属性,如下例所示

class MyWebTests {

	MockMvc mockMvc;

	@BeforeEach
	void setup() {
		mockMvc = standaloneSetup(new AccountController())
			.defaultRequest(get("/")
			.contextPath("/app").servletPath("/main")
			.accept(MediaType.APPLICATION_JSON)).build();
	}
}

上述属性会影响通过MockMvc实例执行的每个请求。如果在给定请求中也指定了相同的属性,则它会覆盖默认值。这就是为什么默认请求中的 HTTP 方法和 URI 无关紧要的原因,因为它们必须在每个请求中指定。