Spring MVC 测试与 HtmlUnit

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

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

更新依赖项

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

使用 HtmlUnit

既然我们已经有了正确的依赖,我们就可以在单元测试中使用HtmlUnit了。我们的示例假定您已经将JUnit添加为依赖项。如果您还没有添加,请相应地更新您的类路径。使用HtmlUnit和Spring MVC Test的完整代码示例可以在 MockMvcHtmlUnitCreateMessageTest 中找到。

创建MockMvc

为了使用HtmlUnit和Spring MVC Test,我们必须首先创建一个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,使用Standalone setup等。重要的是我们需要一个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("https:///mail/messages/form");

注意 主机之后的第一个路径段/mail被视为上下文根。目前不支持上下文根/。请参阅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上@rob_winch。当然,最好的反馈是贡献

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有