Defining Expectations
在执行请求后,你可以通过追加一个或多个 andExpect(..)
调用来定义期望,如下面的示例所示。只要有一个期望失败,就不会断言其他期望。
-
Java
-
Kotlin
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*
mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
import org.springframework.test.web.servlet.get
mockMvc.get("/accounts/1").andExpect {
status { isOk() }
}
在执行请求后,你可以通过追加 andExpectAll(..)
来定义多个期望,如下面的示例所示。与 andExpect(..)
相反,andExpectAll(..)
保证已提供的所有期望都已断言,并跟踪和报告所有失败。
-
Java
-
Kotlin
// static import of MockMvcRequestBuilders.* and MockMvcResultMatchers.*
mockMvc.perform(get("/accounts/1")).andExpectAll(
status().isOk(),
content().contentType("application/json;charset=UTF-8"));
import org.springframework.test.web.servlet.get
mockMvc.get("/accounts/1").andExpectAll {
status { isOk() }
content { contentType(APPLICATION_JSON) }
}
MockMvcResultMatchers.*
提供了许多期望,其中一些期望进一步嵌套了更详细的期望。
期望分为两大类。第一类的断言验证响应的属性(例如,响应状态、标头和内容)。这些是最重要的断言结果。
第二类的断言超出了响应。通过这些断言,你可以检查 Spring MVC 特定的方面,例如处理请求的 controller 方法、是否引发并处理了异常、模型内容、选择的视图、添加的 flash 属性等。它们还允许你检查 Servlet 特定的方面,例如请求和会话属性。
以下测试断言绑定或验证失败:
-
Java
-
Kotlin
mockMvc.perform(post("/persons"))
.andExpect(status().isOk())
.andExpect(model().attributeHasErrors("person"));
import org.springframework.test.web.servlet.post
mockMvc.post("/persons").andExpect {
status { isOk() }
model {
attributeHasErrors("person")
}
}
在编写测试时,多次转储执行请求的结果非常有用。你可以按照以下步骤操作,其中 print()
是 MockMvcResultHandlers
的静态导入:
-
Java
-
Kotlin
mockMvc.perform(post("/persons"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(model().attributeHasErrors("person"));
import org.springframework.test.web.servlet.post
mockMvc.post("/persons").andDo {
print()
}.andExpect {
status { isOk() }
model {
attributeHasErrors("person")
}
}
只要请求处理不会导致未处理的异常,print()
方法就会将所有可用的结果数据打印到 System.out
。还有一个 log()
方法和 print()
方法的另外两个变体,一个接受 OutputStream
,另一个接受 Writer
。例如,调用 print(System.err)
会将结果数据打印到 System.err
,而调用 print(myWriter)
会将结果数据打印到自定义 writer。如果你希望记录结果数据而不是打印结果数据,则可以调用 log()
方法,该方法将结果数据作为 org.springframework.test.web.servlet.result
日志类别的单个 DEBUG
消息记录下来。
在某些情况下,你可能希望直接访问结果并验证无法通过其他方式验证的内容。这可以通过在所有其他期望值后面追加 .andReturn()
来实现,如下面的示例所示:
-
Java
-
Kotlin
MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn();
// ...
var mvcResult = mockMvc.post("/persons").andExpect { status { isOk() } }.andReturn()
// ...
如果所有测试重复相同的期望,则可以在构建 MockMvc
实例时设置一次共同期望,如下面的示例所示:
-
Java
-
Kotlin
standaloneSetup(new SimpleController())
.alwaysExpect(status().isOk())
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
.build()
// Not possible in Kotlin until {kotlin-issues}/KT-22208 is fixed
请注意,共同期望始终被应用,并且无法覆盖,除非创建单独的 MockMvc
实例。
当 JSON 响应内容包含使用https://github.com/spring-projects/spring-hateoas[Spring HATEOAS] 创建的超媒体链接时,您可以使用 JsonPath 表达式来验证所产生的链接,如下例所示:
-
Java
-
Kotlin
mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people"));
mockMvc.get("/people") {
accept(MediaType.APPLICATION_JSON)
}.andExpect {
jsonPath("$.links[?(@.rel == 'self')].href") {
value("http://localhost:8080/people")
}
}
当 XML 响应内容包含使用https://github.com/spring-projects/spring-hateoas[Spring HATEOAS] 创建的超媒体链接时,您可以使用 XPath 表达式来验证所得链接:
-
Java
-
Kotlin
Map<String, String> ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom");
mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML))
.andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people"));
val ns = mapOf("ns" to "http://www.w3.org/2005/Atom")
mockMvc.get("/handle") {
accept(MediaType.APPLICATION_XML)
}.andExpect {
xpath("/person/ns:link[@rel='self']/@href", ns) {
string("http://localhost:8080/people")
}
}