抢先一步
VMware 提供培训和认证,助力您加速发展。
了解更多周一,我宣布了 Spring Test MVC HtmlUnit 首个里程碑版本的发布,并承诺会有一个系列博客来介绍它。这是介绍 Spring Test MVC HtmlUnit 的四部分系列博客中的第一篇。系列大纲如下所示
最明显的问题是:“我为什么需要这个?”最好的答案是通过探索一个非常基础的示例应用来找到。假设你有一个 Spring MVC Web 应用,它允许对 Message 对象进行 CRUD 操作。该应用还允许分页浏览所有消息。你将如何测试它呢?
使用 Spring MVC Test,我们可以轻松测试是否能够创建一个 Message
。
MockHttpServletRequestBuilder createMessage = post("/messages/")
.param("summary", "Spring Rocks")
.param("text", "In case you didn't know, Spring Rocks!");
mockMvc.perform(createMessage)
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/messages/123"));
如果我们想测试用于创建消息的表单视图怎么办?例如,假设我们的表单看起来像下面的片段
<form id="messageForm" action="/messages/" method="post">
<div class="pull-right"><a href="/messages/">Messages</a></div>
<label for="summary">Summary</label>
<input type="text" class="required" id="summary" name="summary" value="" />
<label for="text">Message</label>
<textarea id="text" name="text"></textarea>
<div class="form-actions">
<input type="submit" value="Create" />
</div>
</form>
我们如何确保我们的表单会产生正确的请求来创建新消息?一种简单尝试可能看起来像这样
mockMvc.perform(get("/messages/form"))
.andExpect(xpath("//input[@name='summary']").exists())
.andExpect(xpath("//textarea[@name='text']").exists());
这个测试有一些明显的问题。如果我们更新控制器使用参数“message”而不是“text”,我们的测试就会错误地通过。为了解决这个问题,我们可以结合我们的两个测试
String summaryParamName = "summary";
String textParamName = "text";
mockMvc.perform(get("/messages/form"))
.andExpect(xpath("//input[@name='" + summaryParamName + "']").exists())
.andExpect(xpath("//textarea[@name='" + textParamName + "']").exists());
MockHttpServletRequestBuilder createMessage = post("/messages/")
.param(summaryParamName, "Spring Rocks")
.param(textParamName, "In case you didn't know, Spring Rocks!");
mockMvc.perform(createMessage)
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/messages/123"));
这将降低我们的测试错误通过的风险,但仍然存在一些问题
总体问题是,测试一个网页不是单一的交互。相反,它是用户如何与网页交互以及该网页如何与其他资源交互的组合。例如,表单视图的结果被用作用户创建消息的输入。另一个例子是我们的表单视图利用了额外的资源,比如 JavaScript 验证,这些资源会影响页面的行为。
为了解决上述问题,我们可以进行集成测试,但这有一些明显的缺点。考虑测试允许我们分页浏览消息的视图。我们可能需要以下测试
为了设置这些测试,我们需要确保数据库中包含正确的消息。这导致了一些问题
这些问题并不意味着我们应该完全放弃集成测试。相反,我们可以通过将详细的测试转移到使用 mock 服务来减少集成测试的数量,这将显著提高测试速度。然后,我们可以使用较少的集成测试来验证简单的流程,以确保一切正常协同工作。
那么,如何在测试页面交互的同时仍然获得高性能呢?我相信你已经猜到了……Spring Test MVC HtmlUnit 将使我们能够
注意:与 Spring MVC Test 一样,HtmlUnit 集成将适用于不依赖于 Servlet 容器的模板技术(例如 Thymeleaf, Freemarker, Velocity 等)。它不适用于 JSP,因为 JSP 依赖于 Servlet 容器。
我希望这篇文章能让你对我的下一篇文章感到兴奋,该文章将讨论如何通过集成 Spring Test MVC 和 HtmlUnit 来解决其中的一些问题。
请提供反馈!
如果您对本系列博客或 Spring Test MVC HtmlUnit 有任何反馈,我鼓励您通过 github issues 联系我,或在 twitter @rob_winch 上 ping 我。当然,最好的反馈是以贡献的形式出现。