0

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

class UserPasswordCommand {
    String currentPassword
    //other fields....
    static constraints = {
        currentPassword validator: { currPass, upc ->
            Holders.applicationContext.passwordEncoder.isPasswordValid(
                    Holders.applicationContext.springSecurityService.currentUser.password, currPass, null)
        }
    }
}

但是在单元测试中调用new UserPasswordCommand(...)时,我得到以下信息:

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

所以看起来 springSecurityService = null (如预期的那样)。我尝试了不同的动作来模拟或“元类”它,但没有成功。

请告知是否有更好的方法在命令对象中使用来自 applicationContext 的 bean 或在 Holders.applicationContext 中模拟 bean 的一些方法。

提前致谢!

更新

将以下内容放置到setup()部分:

def setup() {
    def appContext = Mock(ApplicationContext)
    def springSecurityService = Mock(SpringSecurityService)
    appContext.springSecurityService >> springSecurityService
    Holders.metaClass.static.applicationContext = { appContext }
}

但是没有效果。springSecurityService在从Holders检索到的applicationContext中为。我究竟做错了什么?

4

2 回答 2

1

您可以像这样覆盖 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 }
}
于 2017-03-19T15:06:19.297 回答
0

我通过摆脱Holders原始命令对象解决了这个问题:

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)
}

和:

given:
Map props = [
    currentPassword: CURRENT_PASSWORD,
    passwordEncoder: passwordEncoder,
    springSecurityService: springSecurityService,
]

expect:
new UserPasswordCommand(props).validate()
于 2017-03-19T22:58:01.283 回答