MockMvc 与 HtmlUnit
本节介绍如何集成 MockMvc 和 HtmlUnit。如果你想使用原始的 HtmlUnit 库,请使用此选项。
MockMvc 和 HtmlUnit 设置
首先,确保你已经包含了 org.htmlunit:htmlunit
的测试依赖。
我们可以通过使用 MockMvcWebClientBuilder
轻松创建一个与 MockMvc 集成的 HtmlUnit WebClient
,如下所示:
- 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")
默认的上下文路径是 ""
。或者,我们可以指定上下文路径,如 Advanced 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 Framework 为我们加载的 WebApplicationContext
构建一个 WebClient
。以下示例重复了这种方法:
- 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 {kotlin-issues}/KT-22208 is fixed
这种方法虽然更为冗长,但通过使用 MockMvc
实例构建 WebClient
,我们可以充分利用 MockMvc 的全部功能。
有关创建 MockMvc
实例的更多信息,请参阅 配置 MockMvc。