使用 HtmlUnit 测试 Spring MVC

工程 | 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实例有很多文档,但我们将在本节中快速回顾一下如何创建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 过滤器,使用独立设置等。重要的是我们需要一个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://127.0.0.1/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 问题联系我们或在 Twitter 上联系我@rob_winch。当然,最好的反馈是以贡献的形式出现的。

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

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

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

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

查看全部