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

use*_*825 7 grails groovy unit-testing dry helpers

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

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

java.lang.NullPointerException: Cannot invoke method encodePassword() on null object
Run Code Online (Sandbox Code Playgroud)

User.groovy中:

def beforeInsert() {
    // ...
    password = springSecurityService.encodePassword(pw)
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

尽管如此,即使我尝试mockFor()在TestHelper.groovy中调用任何地方,我也会得到一个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)
Run Code Online (Sandbox Code Playgroud)

注意:我目前嘲笑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
}
Run Code Online (Sandbox Code Playgroud)
  1. 关于我如何能够使用帮助程序类而只留下单元测试中的所有模拟的任何想法?
  2. 我最好放置TestHelper.groovy文件,以便在集成和单元测试中使用它?

请注意,当我将所有帮助程序直接移动到UserTests.groovy时,一切正常!

use*_*825 5

解决这个问题的方法是不要user.save()TestHelper.groovy中调用任何一个.

这是有道理的,因为对于许多(单元)测试,持久化(保存)实例无论如何都是不必要的.

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

集成测试的一个工作示例是:

def user = TestHelper.getUserObject()
user.save()
Run Code Online (Sandbox Code Playgroud)

对于单元测试:

def user = TestHelper.getUserObject()
user.springSecurityService = new SpringSecurityService() // or the described mock accordingly
user.save()
Run Code Online (Sandbox Code Playgroud)

这使得任何模拟都不会出现在TestHelper.groovy中