|
对于最新稳定版本,请使用 Spring Framework 7.0.6! |
MockMvc 与 HtmlUnit
本节介绍如何集成 MockMvc 和 HtmlUnit。如果您希望使用原始的 HtmlUnit 库,请选择此选项。
MockMvc 和 HtmlUnit 设置
首先,请确保您已添加了对 net.sourceforge.htmlunit:htmlunit 的测试依赖。为了在 Apache HttpComponents 4.5+ 中使用 HtmlUnit,您需要使用 HtmlUnit 2.18 或更高版本。
我们可以使用 WebClient 轻松创建一个与 MockMvc 集成的 HtmlUnit MockMvcWebClientBuilder,如下所示:
-
Java
-
Kotlin
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 作为服务器引用的 URL 都会被定向到我们的
MockMvc 实例,而无需建立真实的 HTTP 连接。其他任何 URL 则会像平常一样通过网络连接发起请求。这使我们能够轻松测试 CDN 的使用。
MockMvc 和 HtmlUnit 的使用
现在我们可以像平常一样使用 HtmlUnit,而无需将我们的应用程序部署到 Servlet 容器中。例如,我们可以发送请求以创建消息视图,如下所示:
-
Java
-
Kotlin
HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form");
val createMsgFormPage = webClient.getPage("http://localhost/messages/form")
默认上下文路径为 ""。或者,我们可以指定上下文路径,
如 高级 MockMvcWebClientBuilder 中所述。 |
一旦我们获得了对 HtmlPage 的引用,就可以填写表单并提交它以创建一条消息,如下例所示:
-
Java
-
Kotlin
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 库:
-
Java
-
Kotlin
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 测试。 首先,我们不再需要显式地验证表单,然后手动创建一个看起来像该表单的请求。 取而代之的是,我们直接请求表单、填写表单并提交它,从而显著减少了开销。
另一个重要因素是,HtmlUnit 使用 Mozilla Rhino 引擎来执行 JavaScript。这意味着我们还可以测试页面中 JavaScript 的行为。
有关使用 HtmlUnit 的更多信息,请参阅HtmlUnit 文档。
高级MockMvcWebClientBuilder
在迄今为止的示例中,我们以最简单的方式使用了 MockMvcWebClientBuilder,即基于 Spring TestContext 框架为我们加载的 WebClient 来构建一个 WebApplicationContext。以下示例重复使用了这种方法:
-
Java
-
Kotlin
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()
}
我们还可以指定额外的配置选项,如下例所示:
-
Java
-
Kotlin
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 来完成完全相同的设置,如下所示:
-
Java
-
Kotlin
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 https://youtrack.jetbrains.com/issue/KT-22208 is fixed
这种方式更为冗长,但通过使用 WebClient 实例来构建 MockMvc,我们可以充分利用 MockMvc 的全部功能。
有关创建 MockMvc 实例的更多信息,请参阅
设置选项。 |