用 Spock 来测试 Grails Controllers

来源:互联网 发布:淘宝anna家的创始人 编辑:程序博客网 时间:2024/05/16 04:57

原文链接: http://greybeardedgeek.net/2011/05/13/testing-grails-controllers-with-spock/

原文发表时间:2011-05-13

我决定用 Spock 来测试 Grails 项目. Spock 写测试的方式很可爱, 非常推荐.

用 Spock 写单元测试很容易, Spock 的 UnitSpec 类提供了全部你可能做 Grails 项目所期待的 mock 方法,包括 mockDomain, mockForConstraintsTests, 和 friends.

以下用 Spock 单元测试来测一个领域实体:

class CompoundInstanceSpec extends UnitSpec {    def "finding the compound instance's primary name"() {        setup:        mockDomain(CompoundInstance.class)        expect:        !compoundInstance.primaryName        compoundInstance.setupPrimaryName()        compoundInstance.primaryName == name2.name        compoundInstance.compoundNames.remove(name2)        compoundInstance.setupPrimaryName()        !compoundInstance.primaryName        where:        name1 = [name: 'name1', primary: false]        name2 = [name: 'name2', primary: true]        name3 = [name: 'name3', primary: false]        compoundInstance = new CompoundInstance(compoundNames: [name1, name2, name3])    }}

当做 Grails Controller的集成测试时, 我碰到了问题. 第一个问题是 Grails 生成的 controller 代码使用 ValidationTagLib 里的 message() 闭包在 flash scope去显示国际化的消息. 不幸的是 Grail 的集成测试环境里没有 Spock 的 ControllerSpec 类触发 messageSource 实体到应用上下文, 所以 controller试图放入信息success 到flash scope 时测试会失败:

flash.message = "${message(code: 'default.created.message',    args: [message(code: 'compound.label', default: 'Compound'),         results.compoundInstance.primaryName])}"

简单的解决办法 (假如你不需要消息的内容) 是使用 MOP 在测试初始化方法setup里编程重载 controller 的 message() 闭包. 下面的例子始终返回 “mockMessage” 的消息值,并且允许测试正常运行:

setup:controller.metaClass.message = {args -> "mockMessage"}

更复杂的办法是真实触发 messageSource.

第二个问题是我可以运行碰到服务controller里需要得到当前登录的用户 (我使用 spring-security 插件). 当在测试环境下运行时,这里当然没有登录用户啦, 测试也就自然失败了.

简单的解决办法是把测试用 SpringSecurityUtils 的 doWithAuth 闭包裹起来, 指定你需要运行测试相应权限的用户. 当然,你要确认或创建用户,并授权(或角色)在BootStrap.groovy脚本里, 或在测试的初始化方法setup里.

这样,我的集成测试就可以处理这两种情况了。

以下原创
现在看来,更简单的办法是用 @TestFor(SomeController) 和 @Mock(SomeDomain)这两个注解。

2 0
原创粉丝点击