Grails 1.1 测试 - mockForConstraintsTests(class, testInstances = )

这个方法可以对domain类和command对象进行非常详细地模拟设置,它允许你确认各种约束是否按你想要的方式执行。

你测试domain约束了?如果没有,为什么没有?如果你的回答是它们不需要测试,请你三思。

你的各种约束包含逻辑部分,这部分逻辑很容易产生bug,而这类bug很容易被捕捉到,特别的是save()允许失败也不会抛出异常。

而如果你的回答是太难或太烦,现在这已经不再是借口了,可以用mockForConstraintsTests()解决这个问题。

这个方法就像mockDomain()方法的简化版本,简单得对所给的domain类添加一个validate()方法。

你所要做的就是mock这个类,创建带有属性值的实例,然后调用validate()方法。

你可以查看domain实例的errors属性判断这个确认方法是否失败。

所以假如所有我们正在做的是模拟validate()方法,那么可选的测试实例数组参数呢?这就是我们为什么可以测试唯一约束的原因,你很快就可以看见了。

那么假设我们拥有如下的一个简单domain类:class Book { String title String author static constraints = { title(blank: false, unique: true) author(blank: false, minSize: 5) } }不要担心这些约束是否合理,它们在这仅仅是示范作用。

为了测试这些约束,我们可以按下面方法来做:class BookTests extends GrailsUnitTestCase { void testConstraints() { def existingBook = new Book(title: "Misery", author: "Stephen King") mockForConstraintsTests(Book, [ existingBook ]) // Validation should fail if both properties are null. def book = new Book() assertFalse book.validate() assertEquals "nullable", book.errors["title"] assertEquals "nullable", book.errors["author"] // So let's demonstrate the unique and minSize constraints. book = new Book(title: "Misery", author: "JK") assertFalse book.validate() assertEquals "unique", book.errors["title"] assertEquals "minSize", book.errors["author"] // Validation should pass! book = new Book(title: "The Shining", author: "Stephen King") assertTrue book.validate() } }你可以在没有进一步解释的情况下,阅读上面这些代码,思考它们正在做什么事情。

我们会解释的唯一一件事是errors属性使用的方式。

第一,它返回了真实的Spring Errors实例,所以你可以得到你通常期望的所有属性和方法。

第二,这个特殊的Errors对象也可以用如上map/property方式使用。

简单地读取你感兴趣的属性名字,map/property接口会返回被确认的约束名字。

注意它是约束的名字,不是你所期望的信息内容。

这是测试约束讲解部分。我们要讲的最后一件事是用这种方式测试约束会捕捉一个共同的错误:typos in the “constraints” property。

正常情况下这是目前最难捕捉的一个bug,还没有一个约束单元测试可以直接简单得发现这个问题。