如何在使用Spock功能测试grails时设置对象

时间:2013-06-18 15:09:50

标签: grails groovy spock

我有一个示例域名,例如

class User {
    String username
    String password

    def userHelper

    static contraints = {
        username(nullable: false, blank: false)
        password nullable: false, blank: false, validator: {pwd, userInstance ->
            return userInstance.userHelper.validatePassword(pwd)
        }
    }
}

userHelper

中的resources.groovy正在注入beans = { userHelper(UserHelper) }
Cannot invoke method validatePassword() on null object

当我从浏览器测试我的应用程序时,一切运行正常。但是,我在尝试为此编写功能测试时遇到异常。

错误说明:userHelper

所以我假设在运行我的功能测试用例时没有设置 @TestFor(UserController) @Mock([User]) class UserControllerSpecification extends Specification { def "save user" () { given: request.contentType = "application/json" request.JSON = """ {user: { username: "somtething" password: "something" } } """ when: controller.save() then: User.count() == 1 } }

我的测试用例如下:

class UserController {
    def userService
    def save() {
        def user = new User(params?.user)
        request.withFormat {
            json {
                if(user.validate())
                  userService.processUser()
                  //do something
                else
                  //do something else
            }
        }
    }
}

更新

控制器:

userHelper

问题

  • 如何在运行测试之前在User域上设置Bootstrap.groovy属性?
  • 如何在运行所有功能和集成测试用例之前在{{1}}中运行我的代码?

2 个答案:

答案 0 :(得分:4)

您是否尝试过使用defineBeans?由于这是一个单元测试,因此您必须明确定义bean。这通常是在JUnit中完成的

defineBeans{
    userHelper(UserHelper){bean ->
        //in case you have other beans defined inside helper
        bean.autowire = true 
    }
}

您可以在设置方法中defineBeans使其适用于所有测试用例。

@Before
void setup(){
    defineBeans{
        userHelper(UserHelper){bean ->
            //in case you have other beans defined inside helper
            bean.autowire = true 
        }
    }
}   

更新:

似乎在spo​​ck的情况下你可以直接在单元测试中注入一个spring bean(测试扩展Specification

class UserControllerSpecification extends Specification {
    def userHelper //injected here in case of spock

    def "save user" () {
     ................
    }
}

答案 1 :(得分:1)

尝试使用metaClass。

def setup(){
    User.metaClass.getUserHelper = {new UserHelper()}
}

如果这是你想要的,你也可以模拟userHelper。

def setup(){
    def userHelperMock = Mock(UserHelper)
    userHelperMock.validatePassword(_) >> true
    User.metaClass.getUserHelper = {userHelperMock}
}

确保您正在呼叫getUserHelper()直接访问私有userHelper媒体资源。明确这样做可能是个好主意:

password nullable: false, blank: false, validator: {pwd, userInstance ->
    return this.getUserHelper().validatePassword(pwd)
}

@dmahapatro使用defineBeans{...}的答案是最佳方式,但我认为由于this grails bug而无效...

将bean直接注入测试的另一个建议只适用于扩展grails.plugin.spock.IntegrationSpec的集成测试。