此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

MockMvc 和 HtmlUnit

本节介绍如何集成 MockMvc 和 HtmlUnit。如果需要,请使用此选项 以使用原始 HtmlUnit 库。spring-doc.cadn.net.cn

MockMvc 和 HtmlUnit 设置

首先,确保您已包含net.sourceforge.htmlunit:htmlunit.为了将 HtmlUnit 与 Apache HttpComponents 一起使用 4.5+ 时,您需要使用 HtmlUnit 2.18 或更高版本。spring-doc.cadn.net.cn

我们可以轻松创建一个 HtmlUnitWebClient它与 MockMvc 集成,方法是使用MockMvcWebClientBuilder如下:spring-doc.cadn.net.cn

WebClient webClient;

@BeforeEach
void setup(WebApplicationContext context) {
	webClient = MockMvcWebClientBuilder
			.webAppContextSetup(context)
			.build();
}
lateinit var webClient: WebClient

@BeforeEach
fun setup(context: WebApplicationContext) {
	webClient = MockMvcWebClientBuilder
			.webAppContextSetup(context)
			.build()
}
这是一个使用MockMvcWebClientBuilder.对于高级用法, 看高深MockMvcWebClientBuilder.

这可确保引用localhost因为服务器被定向到我们的MockMvc实例,而无需真正的 HTTP 连接。任何其他 URL 为 像往常一样使用网络连接请求。这让我们可以轻松地测试 CDN 的spring-doc.cadn.net.cn

MockMvc 和 HtmlUnit 用法

现在我们可以像往常一样使用 HtmlUnit,但不需要部署我们的 应用程序添加到 Servlet 容器中。例如,我们可以请求视图创建一个 消息中包含以下内容:spring-doc.cadn.net.cn

HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form");
val createMsgFormPage = webClient.getPage("http://localhost/messages/form")
默认上下文路径为 .或者,我们可以指定上下文路径 如""高深MockMvcWebClientBuilder.

一旦我们引用了HtmlPage,然后我们可以填写表格并提交 创建消息,如下例所示:spring-doc.cadn.net.cn

HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm");
HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary");
summaryInput.setValueAttribute("Spring Rocks");
HtmlTextArea textInput = createMsgFormPage.getHtmlElementById("text");
textInput.setText("In case you didn't know, Spring Rocks!");
HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input", "type", "submit");
HtmlPage newMessagePage = submit.click();
val form = createMsgFormPage.getHtmlElementById("messageForm")
val summaryInput = createMsgFormPage.getHtmlElementById("summary")
summaryInput.setValueAttribute("Spring Rocks")
val textInput = createMsgFormPage.getHtmlElementById("text")
textInput.setText("In case you didn't know, Spring Rocks!")
val submit = form.getOneHtmlElementByAttribute("input", "type", "submit")
val newMessagePage = submit.click()

最后,我们可以验证是否已成功创建新消息。以下内容 断言使用 AssertJ 库:spring-doc.cadn.net.cn

assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123");
String id = newMessagePage.getHtmlElementById("id").getTextContent();
assertThat(id).isEqualTo("123");
String summary = newMessagePage.getHtmlElementById("summary").getTextContent();
assertThat(summary).isEqualTo("Spring Rocks");
String text = newMessagePage.getHtmlElementById("text").getTextContent();
assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!");
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123")
val id = newMessagePage.getHtmlElementById("id").getTextContent()
assertThat(id).isEqualTo("123")
val summary = newMessagePage.getHtmlElementById("summary").getTextContent()
assertThat(summary).isEqualTo("Spring Rocks")
val text = newMessagePage.getHtmlElementById("text").getTextContent()
assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!")

前面的代码在许多方面改进了我们的 MockMvc 测试。 首先,我们不再需要显式验证我们的表单,然后创建一个请求 看起来像表格。相反,我们请求表单,填写并提交它,从而 显著降低开销。spring-doc.cadn.net.cn

另一个重要因素是 HtmlUnit 使用 Mozilla Rhino 引擎来评估 JavaScript。这意味着我们还可以测试 JavaScript 在我们页面中的行为。spring-doc.cadn.net.cn

请参阅 HtmlUnit 文档 有关使用 HtmlUnit 的其他信息。spring-doc.cadn.net.cn

高深MockMvcWebClientBuilder

在到目前为止的示例中,我们使用了MockMvcWebClientBuilder以最简单的方式 可能,通过构建一个WebClient基于WebApplicationContext为我们加载 Spring TestContext 框架。以下示例中重复了此方法:spring-doc.cadn.net.cn

WebClient webClient;

@BeforeEach
void setup(WebApplicationContext context) {
	webClient = MockMvcWebClientBuilder
			.webAppContextSetup(context)
			.build();
}
lateinit var webClient: WebClient

@BeforeEach
fun setup(context: WebApplicationContext) {
	webClient = MockMvcWebClientBuilder
			.webAppContextSetup(context)
			.build()
}

我们还可以指定其他配置选项,如下例所示:spring-doc.cadn.net.cn

WebClient webClient;

@BeforeEach
void setup() {
	webClient = MockMvcWebClientBuilder
		// demonstrates applying a MockMvcConfigurer (Spring Security)
		.webAppContextSetup(context, springSecurity())
		// for illustration only - defaults to ""
		.contextPath("")
		// By default MockMvc is used for localhost only;
		// the following will use MockMvc for example.com and example.org as well
		.useMockMvcForHosts("example.com","example.org")
		.build();
}
lateinit var webClient: WebClient

@BeforeEach
fun setup() {
	webClient = MockMvcWebClientBuilder
		// demonstrates applying a MockMvcConfigurer (Spring Security)
		.webAppContextSetup(context, springSecurity())
		// for illustration only - defaults to ""
		.contextPath("")
		// By default MockMvc is used for localhost only;
		// the following will use MockMvc for example.com and example.org as well
		.useMockMvcForHosts("example.com","example.org")
		.build()
}

作为替代方案,我们可以通过配置MockMvc实例,并将其提供给MockMvcWebClientBuilder如下:spring-doc.cadn.net.cn

MockMvc mockMvc = MockMvcBuilders
		.webAppContextSetup(context)
		.apply(springSecurity())
		.build();

webClient = MockMvcWebClientBuilder
		.mockMvcSetup(mockMvc)
		// for illustration only - defaults to ""
		.contextPath("")
		// By default MockMvc is used for localhost only;
		// the following will use MockMvc for example.com and example.org as well
		.useMockMvcForHosts("example.com","example.org")
		.build();
// Not possible in Kotlin until {kotlin-issues}/KT-22208 is fixed

这更详细,但是,通过构建WebClient替换为MockMvc实例中,我们有 MockMvc 的全部功能触手可及。spring-doc.cadn.net.cn

有关创建MockMvc实例,请参阅 设置选项