首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

精通 Grails 使用 Grails 进行单元测试(2)

精通 Grails 使用 Grails 进行单元测试(2)

理解 mockForConstraintsTests()要在单元测试中模拟 Grails 验证,添加 mockForConstraintsTests() 方法,如清单 6 所示。此方法指示 Grails 将验证方法元编程到指定的域类上,就像通常在运行时所做的一样。
清单 6. 将会通过的测试,这得益于 mockForConstraintsTests()
1
2
3
4
5
void testBlank() {
  mockForConstraintsTests(User)
  def user = new User()
  assertFalse user.validate()
}




现在,运行测试来验证它是否会通过,如清单 7 所示:
清单 7. 运行将会通过的测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ grails test-app -unit User
Environment set to test

Starting unit tests ...
Running tests of type 'unit'
-------------------------------------------------------
Running 1 unit test...
Running test UserTests...PASSED
Tests Completed in 635ms ...
-------------------------------------------------------
Tests passed: 1
Tests failed: 0
-------------------------------------------------------

Tests PASSED - view reports in /testing/test/reports.




要进一步细化单元测试,您可以断言验证会因为特定字段上的特定约束而失败,如清单 8 所示。mockForConstraintsTests() 方法将 errors 集合元编程到域类上。此 errors 集合简化了对是否触发了正确的约束的验证。
清单 8. 断言特定字段上的一个特定约束违规
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void testBlank() {
  mockForConstraintsTests(User)
  def user = new User()
  assertFalse user.validate()

  println "=" * 20
  println "Total number of errors:"
  println user.errors.errorCount

  println "=" * 20
  println "Here are all of the errors:"
  println user.errors

  println "=" * 20
  println "Here are the errors individually:"
  user.errors.allErrors.each{
    println it
    println "-" * 20
  }

  assertEquals "blank", user.errors["name"]
}




重新运行此测试。它还会意外地失败吗?查看报告输入(如图 3 所示),找出问题根源:
图 3. 用空值替代空格导致的失败错误消息为 expected:<[blank]> but was:<[nullable]>。验证失败了,但原因并不是您所期望的那样。
很容易遇到这种错误。在 Grails 中,默认情况下,域类中的所有字段必须非空。这项隐含限制的问题在于,您通常会通过 HTML 表单与 Grails 交互。如果在 HTML 表单中将 String 字段保留为空,paramsMap 中的控制器会将其看作空 String(也就是 ""),而不是 null。
如果单击 HTML 报告底部的 System.out 链接,可以看到 3 个 String 字段(name、login 和 password)都抛出了 nullable 约束违规错误。图 4 显示了 println 调用的输出。只有 role 字段 — 其默认值为 user — 通过隐含的 nullable 约束。
图 4. 测试的 System.out 输出再次调整 testBlank() 测试,确保验证因合适的原因而失败(从而使单元测试通过),如清单 9 所示:
清单 9. 测试现在因正确的原因得以通过
1
2
3
4
5
6
7
8
9
void testBlank() {
  mockForConstraintsTests(User)
  def user = new User(name:"",
                      login:"admin",
                      password:"wordpass")
  assertFalse user.validate()
  assertEquals 1, user.errors.errorCount
  assertEquals "blank", user.errors["name"]
}




在重新运行测试以确保其通过时,可以解决一个稍微棘手一些的约束:unique。
返回列表