执行请求
本节介绍如何使用MockMvcTester
执行请求及其集成
替换为 AssertJ 来验证响应。
MockMvcTester
提供了一个 Fluent API 来编写重用相同MockHttpServletRequestBuilder
作为 Hamcrest 支持,只是没有必要
以导入静态方法。返回的构建器是 AssertJ 感知的,因此
将其包装在常规的assertThat()
factory 方法触发 Exchange,而
提供对MvcTestResult
.
下面是一个执行POST
上/hotels/42
并配置
请求指定Accept
页眉:
-
Java
-
Kotlin
assertThat(mockMvc.post().uri("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON))
. // ...
assertThat(mockMvc.post().uri("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON))
. // ...
AssertJ 通常由多个assertThat()
语句来验证不同的
部分交易所。与上述情况中只有一个声明不同,您
可以使用.exchange()
要返回MvcTestResult
可用于多个assertThat
语句:
-
Java
-
Kotlin
MvcTestResult result = mockMvc.post().uri("/hotels/{id}", 42)
.accept(MediaType.APPLICATION_JSON).exchange();
assertThat(result). // ...
val result = mockMvc.post().uri("/hotels/{id}", 42)
.accept(MediaType.APPLICATION_JSON).exchange()
assertThat(result)
. // ...
您可以在 URI 模板样式中指定查询参数,如下例所示:
-
Java
-
Kotlin
assertThat(mockMvc.get().uri("/hotels?thing={thing}", "somewhere"))
. // ...
assertThat(mockMvc.get().uri("/hotels?thing={thing}", "somewhere"))
. // ...
您还可以添加表示 query 或 form 的 Servlet 请求参数 参数,如下例所示:
-
Java
-
Kotlin
assertThat(mockMvc.get().uri("/hotels").param("thing", "somewhere"))
. // ...
assertThat(mockMvc.get().uri("/hotels").param("thing", "somewhere"))
. // ...
如果应用程序代码依赖 Servlet 请求参数,并且不检查查询
string (通常是这种情况),使用哪个选项并不重要。
但请记住,随 URI 模板提供的查询参数将被解码
虽然请求参数通过param(…)
方法应该已经
被解码。
异步
如果请求的处理是异步完成的,exchange()
等待
完成请求,以便 assert 的结果实际上是不可变的。
默认超时为 10 秒,但可以根据逐个请求进行控制
basis 中,如以下示例所示:
-
Java
-
Kotlin
assertThat(mockMvc.get().uri("/compute").exchange(Duration.ofSeconds(5)))
. // ...
assertThat(mockMvc.get().uri("/compute").exchange(Duration.ofSeconds(5)))
. // ...
如果您希望获取原始结果并管理异步
请求自己,使用asyncExchange
而不是exchange
.
多部分
您可以执行内部使用MockMultipartHttpServletRequest
这样就不会实际解析 multipart
请求。相反,您必须将其设置为类似于以下示例:
-
Java
-
Kotlin
assertThat(mockMvc.post().uri("/upload").multipart()
.file("file1.txt", "Hello".getBytes(StandardCharsets.UTF_8))
.file("file2.txt", "World".getBytes(StandardCharsets.UTF_8)))
. // ...
assertThat(mockMvc.post().uri("/upload").multipart()
.file("file1.txt", "Hello".toByteArray(StandardCharsets.UTF_8))
.file("file2.txt", "World".toByteArray(StandardCharsets.UTF_8)))
. // ...
使用 Servlet 和上下文路径
在大多数情况下,最好将上下文路径和 Servlet 路径保留在
请求 URI 的 URI 请求 URI如果您必须使用完整的请求 URI 进行测试,请务必将contextPath
和servletPath
因此,请求映射可以正常工作,如下例所示
显示:
-
Java
-
Kotlin
assertThat(mockMvc.get().uri("/app/main/hotels/{id}", 42)
.contextPath("/app").servletPath("/main"))
. // ...
assertThat(mockMvc.get().uri("/app/main/hotels/{id}", 42)
.contextPath("/app").servletPath("/main"))
. // ...
在前面的示例中,将contextPath
和servletPath
与每个执行的请求一起。相反,您可以设置默认请求
属性,如下例所示:
-
Java
-
Kotlin
MockMvcTester mockMvc = MockMvcTester.of(List.of(new HotelController()),
builder -> builder.defaultRequest(get("/")
.contextPath("/app").servletPath("/main")
.accept(MediaType.APPLICATION_JSON)).build());
val mockMvc =
MockMvcTester.of(listOf(HotelController())) { builder: StandaloneMockMvcBuilder ->
builder.defaultRequest<StandaloneMockMvcBuilder>(
MockMvcRequestBuilders.get("/")
.contextPath("/app").servletPath("/main")
.accept(MediaType.APPLICATION_JSON)
).build()
}
上述属性会影响通过mockMvc
实例。
如果在给定请求中也指定了相同的属性,它将覆盖默认值
价值。这就是为什么默认请求中的 HTTP 方法和 URI 无关紧要的原因,因为
必须在每个请求中指定它们。