圣杯。测试内置Springbean的命令对象
我在自定义验证器中使用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
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()