抢先一步
VMware 提供培训和认证,助力您的快速成长。
了解更多在我上一篇博文中,我介绍了 Spring Test MVC HtmlUnit 并解释了该项目的动机。在这篇博文中,我将介绍如何结合使用 Spring MVC Test 和HtmlUnit。
在使用该项目之前,您必须确保更新您的依赖。有关Maven 和Gradle 的说明可以在网站文档中找到。
现在我们已经有了正确的依赖,我们可以在单元测试中使用 HtmlUnit。我们的示例假设您已经有了 JUnit 依赖。如果您还没有添加它,请相应地更新您的 classpath。使用 HtmlUnit 和 Spring MVC Test 的完整代码示例可以在MockMvcHtmlUnitCreateMessageTest 中找到。
为了使用 HtmlUnit 和 Spring MVC Test,我们首先需要创建一个 MockMvc
实例。关于如何创建 MockMvc
实例的文档很多,但我们将在这里快速回顾一下如何创建 MockMvc
实例。
第一步是创建一个新的 JUnit 类,并按如下所示进行注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebMvcConfig.class, MockDataConfig.class})
@WebAppConfiguration
public class MockMvcHtmlUnitCreateMessageTest {
@Autowired
private WebApplicationContext context;
...
}
@RunWith(SpringJUnit4ClassRunner.class)
允许 Spring 对我们的 MockMvcHtmlUnitCreateMessageTest
进行依赖注入。这就是为什么我们的 @Autowired
注解会生效。@ContextConfiguration
告诉 Spring 要加载哪些配置。您会注意到我们正在加载数据层的模拟实例,以提高测试性能。如果需要,我们也可以选择针对真实数据库运行测试。然而,这会带来我们之前提到的缺点。@WebAppConfiguration
表示 SpringJUnit4ClassRunner
应该创建一个 WebApplicationContext
而不是一个 ApplicationContext
。接下来,我们需要从 context
创建我们的 MockMvc
实例。下面提供了一个示例
@Before
public void setup() {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
...
}
当然,这只是创建 MockMvc
实例的一种方式。我们可以选择添加 Servlet Filter,使用独立设置 等方式。重要的是我们需要一个 MockMvc
实例。有关创建 MockMvc
实例的更多信息,请参考Spring MVC Test 文档。
创建好 MockMvc
实例后,我们需要创建一个 HtmlUnit WebClient
。我们使用 MockMvcWebConnection
来确保 HtmlUnit 使用我们在上一步创建的 MockMvc
实例。
private WebClient webClient;
@Before
public void setup() {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
webClient = new WebClient();
webClient.setWebConnection(new MockMvcWebConnection(mockMvc));
}
现在我们可以像往常一样使用 HtmlUnit,而无需部署我们的应用。例如,我们可以通过以下方式请求创建消息的视图:
HtmlPage createMsgFormPage =
webClient.getPage("http://localhost/mail/messages/form");
注意 主机名后的第一个路径段,/mail
,被视为上下文根(context root)。当前不支持以 /
作为上下文根。参阅spring-test-mvc-htmlunit/issues/20 以获取相关更新。
然后我们可以填写表单并提交它来创建消息。
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();
最后,我们可以验证是否成功创建了新消息
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!");
这在许多方面改进了我们的MockMvc 测试。首先,我们不再需要显式地验证表单,然后创建一个看起来像表单的请求。相反,我们请求表单,填写它,然后提交。这显著减少了开销。
另一个重要因素是HtmlUnit 使用 Mozilla Rhino 引擎来评估页面上的 JavaScript。这意味着我们也可以验证我们的 JavaScript 方法!
有关完整示例,请参考MockMvcHtmlUnitCreateMessageTest。参考HtmlUnit 文档以获取有关使用 HtmlUnit 的更多信息。
HtmlUnit
大大提高了我们的生产力和测试范围。然而,我们可以通过增加更高层次的抽象来进一步改进我们的测试。在我们的下一篇博文中,我们将看到如何将 WebDriver
与 MockMvc
结合使用,使我们的测试代码更具可重用性。
请提供反馈!
如果您对此系列博文或 Spring Test MVC HtmlUnit 有反馈,欢迎通过GitHub Issues 联系我,或在 Twitter 上 ping 我 @rob_winch。当然,最好的反馈是以贡献的形式提供的。