Spring MVC Test 与 HtmlUnit

工程 | Rob Winch | 2014年3月25日 | ...

在我上一篇博文中,我介绍了 Spring Test MVC HtmlUnit 并解释了该项目的动机。在这篇博文中,我将介绍如何结合使用 Spring MVC Test 和HtmlUnit

更新依赖

在使用该项目之前,您必须确保更新您的依赖。有关MavenGradle 的说明可以在网站文档中找到。

使用 HtmlUnit

现在我们已经有了正确的依赖,我们可以在单元测试中使用 HtmlUnit。我们的示例假设您已经有了 JUnit 依赖。如果您还没有添加它,请相应地更新您的 classpath。使用 HtmlUnit 和 Spring MVC Test 的完整代码示例可以在MockMvcHtmlUnitCreateMessageTest 中找到。

创建 MockMvc

为了使用 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 文档

初始化 HtmlUnit

创建好 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

现在我们可以像往常一样使用 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 大大提高了我们的生产力和测试范围。然而,我们可以通过增加更高层次的抽象来进一步改进我们的测试。在我们的下一篇博文中,我们将看到如何将 WebDriverMockMvc 结合使用,使我们的测试代码更具可重用性。


请提供反馈!

如果您对此系列博文或 Spring Test MVC HtmlUnit 有反馈,欢迎通过GitHub Issues 联系我,或在 Twitter 上 ping 我 @rob_winch。当然,最好的反馈是以贡献的形式提供的。

获取 Spring 新闻通讯

订阅 Spring 新闻通讯,保持联系

订阅

抢先一步

VMware 提供培训和认证,助力您的快速成长。

了解更多

获取支持

Tanzu Spring 通过一种简单的订阅方式提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

近期活动

查看 Spring 社区的所有近期活动。

查看全部