如何正确地将grails单元测试助手方法移动到单独的文件中?

时间:2011-05-11 20:31:04

标签: unit-testing grails groovy dry helpers

我有一些经常使用的帮助方法,用于将单元测试放入单独的文件中。例如,我的想法是允许我的XYZTests.groovy调用TestHelper.getUserObject()以获得完全初始化的User实例。

现在的问题是,在用户的springSecurityService.encodePassword(pw)中调用beforeInsert()总是失败,因为在TestHelper.groovy中没有模拟springSecurityService

java.lang.NullPointerException: Cannot invoke method encodePassword() on null object

User.groovy

def beforeInsert() {
    // ...
    password = springSecurityService.encodePassword(pw)
    // ...
}

注意:我想避免在 TestHelper.groovy中使用任何模拟,以便在集成测试中使用它的方法。

尽管如此,即使我试图在TestHelper.groovy中的任何地方调用mockFor(),我也会得到一个MME:

No signature of method: static myproject.TestHelper.mockFor() is applicable for argument types: (java.lang.Class, java.lang.Boolean) values: [class grails.plugins.springsecurity.SpringSecurityService, true]
groovy.lang.MissingMethodException: No signature of method: static myproject.TestHelper.mockFor() is applicable for argument types: (java.lang.Class, java.lang.Boolean) values: [class grails.plugins.springsecurity.SpringSecurityService, true]
    at myproject.TestHelper.mockSpringSecurityService(TestHelper.groovy:59)
    at myproject.TestHelper$mockSpringSecurityService.callStatic(Unknown Source)
    at myproject.TestHelper.getUserObject(TestHelper.groovy:47)
    at myproject.TestHelper$getUserObject.call(Unknown Source)
    at myproject.UserTests.setUp(UserTests.groovy:26)

注意:我目前正在嘲笑springSecurityService.encodePassword

// in UserTests.groovy
protected void setUp() {
    // mockDomain(...) and such here

    def u = TestHelper.getUserObject("Pummel")
    u.springSecurityService = mockSpringSecurityService()
    assert u.save()
}
private mockSpringSecurityService() {
    def ssService = mockFor(SpringSecurityService,true)
    ssService.metaClass.encodePassword() { password ->
        "08a2d3c63bf9fc88276d97a9e8df5f841fd772724ad10f119f7e516f228b74c6"
    }

    ssService
}
  1. 关于我如何能够使用帮助程序类而只留下单元测试中的所有模拟的任何想法?
  2. 我最好放置TestHelper.groovy文件,以便在集成和单元测试中使用它吗?
  3. 请注意,当我将所有帮助程序直接移动到UserTests.groovy时,一切正常!

2 个答案:

答案 0 :(得分:5)

解决方法是克制不要调用 TestHelper.groovy 中的任何user.save()

这是有道理的,就像许多(单元)测试一样,持久化(保存)的实例无论如何都是不必要的。

另一方面,许多案例实际上需要未保存的内容。 (例如,为了测试.save()本身的某些效果)

集成测试的工作示例将是:

def user = TestHelper.getUserObject()
user.save()

对于单元测试:

def user = TestHelper.getUserObject()
user.springSecurityService = new SpringSecurityService() // or the described mock accordingly
user.save()

这可以防止任何模拟出TestHelper.groovy

答案 1 :(得分:2)

  1. TestHelper中,您可以使用Groovy ExpandoMetaClass metaClass.static在SpringSecurityService上为encodePassword打一个模拟闭包:

    SpringSecurityService.metaClass.'static'.encodePassword = {'08a2d3c63bf9fc88276d97a9e8df5f841fd772724ad10f119f7e516f228b74c6'}
    
  2. 我会把这个类放在src / groovy下的测试包中