Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
圣杯。测试内置Springbean的命令对象_Spring_Unit Testing_Grails_Spock_Command Objects - Fatal编程技术网

圣杯。测试内置Springbean的命令对象

圣杯。测试内置Springbean的命令对象,spring,unit-testing,grails,spock,command-objects,Spring,Unit Testing,Grails,Spock,Command Objects,我在自定义验证器中使用SpringBean有一个带有约束的命令对象: class UserPasswordCommand { String currentPassword //other fields.... static constraints = { currentPassword validator: { currPass, upc -> Holders.applicationContext.passwordEncode

我在自定义验证器中使用SpringBean有一个带有约束的命令对象:

class UserPasswordCommand {
    String currentPassword
    //other fields....
    static constraints = {
        currentPassword validator: { currPass, upc ->
            Holders.applicationContext.passwordEncoder.isPasswordValid(
                    Holders.applicationContext.springSecurityService.currentUser.password, currPass, null)
        }
    }
}
但是当调用新的UserPasswordCommand时。。。在单元测试中,我得到以下结果:

java.lang.NullPointerException:无法获取上的属性“currentUser” 空对象

因此,springSecurityService似乎与预期的一样为null。我尝试了不同的操作来模拟或元类化它,但没有成功

请告知是否有更好的方法在command对象中使用applicationContext中的bean,或者有一些方法在Holders.applicationContext中模拟bean

提前谢谢

更新

将以下内容放置到“设置”部分:


但没有效果。从持有者检索到的applicationContext中springSecurityService为空。我做错了什么?

您可以像这样覆盖Holder.applicationContext:

  def setup() {
    ApplicationContext appContext = Mock()
    PasswordEncoder passwordEncoder = Mock()
    passwordEncoder.isPasswordValid(_, _, _) >> true

    appContext.passwordEncoder >> passwordEncoder //you can do the same for springSecurityService

    //override Holder.getAplicationContext() method to return mocked context
    Holders.metaClass.static.applicationContext = { appContext }
}

我通过删除原始命令对象中的持有者解决了此问题:

class UserPasswordCommand {
    static passwordEncoder
    static springSecurityService
    String currentPassword
    //...
    static constraints = {
        currentPassword validator: { currPass, upc ->
    passwordEncoder.isPasswordValid(springSecurityService.currentUser.password, currPass, null)
        }
    //...
    }
}
将模拟/存根添加到测试:

def springSecurityService = Mock(SpringSecurityService)
def passwordEncoder = Mock(PasswordEncoder)

def setup() {
    passwordEncoder.isPasswordValid(_, _, _) >> Boolean.TRUE
    springSecurityService.currentUser >> Mock(User)
}
以及:


你是指持卡人而不是持卡人吗?可能是元类而不是元类?是的,很抱歉我无法访问笔记本,我刚刚更正了我的答案没有效果。我已经用新的设置部分更新了这个问题。仅供参考,在命令对象中使用holder是一个非常糟糕的主意。它将表现不佳。更好的方法是使用bean构造函数参数并自己构造类。@JamesKleeh,谢谢你提供的信息。我将从持有者检索更改为普通DI,并将字段设置为静态。这个解决方案足够好吗?
def springSecurityService = Mock(SpringSecurityService)
def passwordEncoder = Mock(PasswordEncoder)

def setup() {
    passwordEncoder.isPasswordValid(_, _, _) >> Boolean.TRUE
    springSecurityService.currentUser >> Mock(User)
}
given:
Map props = [
    currentPassword: CURRENT_PASSWORD,
    passwordEncoder: passwordEncoder,
    springSecurityService: springSecurityService,
]

expect:
new UserPasswordCommand(props).validate()