定义期望

您可以在执行请求后附加一个或多个andExpect(..)调用来定义期望,如下例所示。一旦一个期望失败,将不会断言其他期望。

  • Java

  • Kotlin

// MockMvcRequestBuilders.* 和 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

// MockMvcRequestBuilders.* 和 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特定方面,例如处理请求的控制器方法、是否引发并处理了异常、模型的内容、选择的视图、添加的闪存属性等。它们还让您检查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)会将结果数据打印到自定义写入器。如果希望将结果数据记录而不是打印,可以调用log()方法,该方法将结果数据作为单个DEBUG消息记录在org.springframework.test.web.servlet.result日志类别下。

在某些情况下,您可能希望直接访问结果并验证无法以其他方式验证的内容。可以在所有其他期望之后附加.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()
// 在 {kotlin-issues}/KT-22208 修复之前,无法在Kotlin中实现

请注意,常见的期望始终被应用,无法在不创建单独的MockMvc实例的情况下覆盖。

当JSON响应内容包含使用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响应内容包含使用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")
	}
}