MockMvc 和 Geb

在上一节中,我们了解了如何将 MockMvc 与 WebDriver 结合使用。在本节中,我们将使用Geb 使我们的测试更加 Groovy 化。

为什么选择 Geb 和 MockMvc?

Geb 以 WebDriver 为后盾,因此它提供了许多我们从 WebDriver 获得的相同优势。但是,Geb 通过为我们处理一些样板代码,使事情变得更加容易。

MockMvc 和 Geb 设置

我们可以轻松地使用使用 MockMvc 的 Selenium WebDriver 初始化 Geb Browser,如下所示

def setup() {
	browser.driver = MockMvcHtmlUnitDriverBuilder
		.webAppContextSetup(context)
		.build()
}
这是一个使用MockMvcHtmlUnitDriverBuilder的简单示例。有关更高级的用法,请参阅高级MockMvcHtmlUnitDriverBuilder

这确保了任何引用localhost作为服务器的 URL 都将定向到我们的MockMvc实例,而无需真正的 HTTP 连接。任何其他 URL 都将通过使用网络连接以正常方式请求。这使我们可以轻松地测试 CDN 的使用。

MockMvc 和 Geb 用法

现在我们可以像平时一样使用 Geb,但无需将我们的应用程序部署到 Servlet 容器。例如,我们可以使用以下方法请求创建消息的视图

to CreateMessagePage

然后,我们可以填写表单并提交它以创建消息,如下所示

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

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

与直接使用 WebDriver 一样,这通过使用页面对象模式改进了我们HtmlUnit 测试的设计。如前所述,我们可以将页面对象模式与 HtmlUnit 和 WebDriver 结合使用,但使用 Geb 则更加容易。考虑我们新的基于 Groovy 的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

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

then:
at CreateMessagePage
errors.contains('This field is required.')
我们在闭包中使用断言,以便如果我们在错误的页面上,我们可以确定问题出在哪里。

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

最后,我们可以验证新消息是否已成功创建,如下所示

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

有关如何充分利用 Geb 的更多详细信息,请参阅Geb 使用手册