Spring MVC 测试与 Geb

工程 | Rob Winch | 2014 年 4 月 15 日 | ...

在我的第三篇文章中,我讨论了如何使用WebDriver 结合 Page Object Pattern 来简化我们的测试设计。在这篇文章中,我将讨论如何使用 Geb 来让我们的 MockMvc 测试更具 Groovy 风格。

为什么使用 Geb 和 MockMvc

Geb 基于 WebDriver,因此它提供了许多与 WebDriver 相同的优势。然而,Geb 通过处理一些样板代码,使事情变得更加简单。当然,我们希望使用 MockMvc,这样就不需要将我们的代码部署到服务器上。理解使用 Geb 的好处最简单的方法就是看一个例子。


注意:Geb 的另一个很棒的功能是它出色的文档


更新依赖项

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

使用 Geb

现在我们有了正确的依赖项,我们可以在单元测试中使用 Geb。关于使用 Geb 和 Spring MVC Test 的完整代码示例可以在GebCreateMessagesSpec 中找到。

创建 MockMvc 实例

为了使用 HtmlUnit 和 Spring MVC Test,我们必须首先创建一个 MockMvc 实例。关于如何创建 MockMvc 实例的文档有很多,但我们将在本节中快速回顾如何创建 MockMvc 实例。

第一步是创建一个新的 GebReportingSpec 类,并按如下方式进行注解

@ContextConfiguration(classes=[WebMvcConfig,MockDataConfig])
@WebAppConfiguration
class GebCreateMessagesSpec extends GebReportingSpec {
  @Autowired
  WebApplicationContext context;

  WebDriver driver;

  ...
}
  • 为使此功能正常工作,请确保按照更新依赖项部分中的说明添加 spock-spring 依赖项。这就是为什么 @Autowired 注解会被尊重的原因。
  • @ContextConfiguration告诉Spring加载哪个配置。您会注意到我们正在加载一个模拟的数据库层实例以提高测试性能。如果我们愿意,也可以选择在真实数据库上运行测试。然而,这存在我们之前提到过的缺点。
  • @WebAppConfiguration 指示应创建 WebApplicationContext 而不是 ApplicationContext

接下来,我们需要从context创建我们的MockMvc实例。下面提供了一个如何做到这一点的示例

def setup() {
  MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build()
  ...
}

当然,这只是创建MockMvc实例的一种方式。我们也可以选择添加Servlet Filter,使用Standalone setup等。重要的是我们需要一个MockMvc的实例。有关创建MockMvc实例的更多信息,请参阅Spring MVC Test文档

初始化 WebDriver

现在我们已经创建了 MockMvc 实例,我们需要创建一个 MockMvcHtmlUnitDriver,它确保我们使用的是在上一步中创建的 MockMvc 实例。然后,我们使用 Geb 的显式生命周期并将驱动程序设置在 Geb 的Browser 实例上。

WebDriver driver;

def setup() {
  MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build()
  driver = new MockMvcHtmlUnitDriver(mockMvc, true)
  browser.driver = driver
}

def destroy() {
  if(driver != null) {
    driver.close();
  }
}

使用 Geb

现在我们可以像平常一样使用 Geb,而无需部署我们的应用程序。例如,我们可以通过以下方式请求创建消息的视图

to CreateMessagePage

然后,我们可以填写表单并提交以创建消息。

form.summary = expectedSummary
form.text = expectedMessage
submit.click(ViewMessagePage)

任何未识别的方法调用或属性访问/引用(如果找不到)将被转发到当前页面对象。这消除了我们直接使用 WebDriver 时需要的许多样板代码。

此外,这改进了我们HtmlUnit 测试的设计。最明显的变化是我们现在正在使用页面对象模式。正如我们在为什么是 WebDriver?中提到的,我们可以使用页面对象模式与 HtmlUnit 结合,但现在它要容易得多。

让我们看一下我们的 CreateMessagePage

class CreateMessagePage extends Page {
  static url = 'messages/form'
  static at = { assert title == 'Messages : Create'; true }
  static content =  {
    submit { $('input[type=submit]') }
    form { $('form') }
    errors(required:false) { $('label.error, .alert-error')?.text() }
  }
}

您注意到的第一件事是我们的 CreateMessagePage 扩展了 Page。我们不会详细介绍 Page 的细节,但总而言之,它包含了所有页面所需的基本功能。

接下来您会注意到我们定义了该页面可以找到的 URL。这允许我们通过以下方式导航到页面

to CreateMessagePage

我们还有一个闭包,用于确定我们是否在指定的页面上。如果我们在正确的页面上,它应该返回 true。这就是为什么我们可以使用以下方式断言我们在正确的页面上


注意:我们在闭包中使用断言,这样如果我们在错误的页面上,我们就可以确定哪里出了问题。


at CreateMessagePage

最后,我们创建一个内容闭包,它指定页面内所有感兴趣的区域。我们可以使用类似 jQuery 的导航器 API来选择我们感兴趣的内容。

最后,我们可以验证是否成功创建了新消息

at ViewMessagePage
success == 'Successfully created a new message'
id
date
summary == expectedSummary
message == expectedMessage

欢迎反馈!

如果您对这个博客系列或 Spring Test MVC HtmlUnit 有任何反馈,我鼓励您通过下面的评论、github issues 或在 Twitter 上@rob_winch 与我联系。当然,最好的反馈是以贡献的形式出现的。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

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

了解更多

获得支持

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

了解更多

即将举行的活动

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

查看所有