执行请求

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

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

  • Java

  • Kotlin

// static import of MockMvcRequestBuilders.*

mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
import org.springframework.test.web.servlet.post

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

你还可以执行内部使用 `MockMultipartHttpServletRequest` 的文件上传请求,这样就不会实际解析 multipart 请求。你需要进行如下设置,使其类似于以下示例

  • Java

  • Kotlin

mockMvc.perform(multipart("/doc").file("a1", "ABC".getBytes("UTF-8")));
import org.springframework.test.web.servlet.multipart

mockMvc.multipart("/doc") {
	file("a1", "ABC".toByteArray(charset("UTF8")))
}

你可以使用 URI 模板风格指定查询参数,示例如下所示

  • Java

  • Kotlin

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

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

  • Java

  • Kotlin

mockMvc.perform(get("/hotels").param("thing", "somewhere"));
import org.springframework.test.web.servlet.get

mockMvc.get("/hotels") {
	param("thing", "somewhere")
}

如果应用代码依赖于 Servlet 请求参数并且没有显式检查查询字符串(这通常是情况),则使用哪种选项无关紧要。但是请记住,通过 URI 模板提供的查询参数会被解码,而通过 `param(…​)` 方法提供的请求参数则预期已经解码。

在大多数情况下,最好将 context path 和 Servlet path 从请求 URI 中排除。如果你必须使用完整的请求 URI 进行测试,请确保相应地设置 `contextPath` 和 `servletPath`,以便请求映射正常工作,示例如下所示

  • Java

  • Kotlin

mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main"))
import org.springframework.test.web.servlet.get

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

在上面的示例中,在每次执行请求时都设置 `contextPath` 和 `servletPath` 会很麻烦。相反,你可以设置默认请求属性,示例如下所示

  • Java

  • Kotlin

class MyWebTests {

	MockMvc mockMvc;

	@BeforeEach
	void setup() {
		mockMvc = standaloneSetup(new AccountController())
			.defaultRequest(get("/")
			.contextPath("/app").servletPath("/main")
			.accept(MediaType.APPLICATION_JSON)).build();
	}
}
// Not possible in Kotlin until {kotlin-issues}/KT-22208 is fixed

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