【问题标题】:Unit testing a domain with transient property对具有瞬态属性的域进行单元测试
【发布时间】:2012-08-29 14:50:17
【问题描述】:

我正在尝试对 Spring Security Core Plugin 生成的用户域的控制器进行单元测试。控制器是使用 grails generate-all 生成的。 该域有一个名为 springSecurityService 的瞬态属性。在我的单元测试中,我试图模拟该服务并将这个瞬态变量分配给我的模拟版本。但是,我收到此错误:

No such property: springSecurityService for class: com.myapp.security.SecUser Possible solutions:
springSecurityService groovy.lang.MissingPropertyException: No such property: springSecurityService for class: 
com.myapp.security.SecUser at com.myapp.security.SecUserControllerTests.setUp(SecUserControllerTests.groovy:26)

这是我的域的样子:

class SecUser {
    transient springSecurityService
    String username
    String password
    boolean enabled
    boolean accountExpired
    ....
    def beforeInsert() {
        encodePassword()
    }
    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}

这是我的测试的样子:

 package com.myapp.security

 import org.junit.*
 import grails.test.mixin.*
 import com.myapp.system.*
 import grails.plugins.springsecurity.*

 @TestFor(SecUserController)
 @Mock([SecUser,SpringSecurityService])
 class SecUserControllerTests {

    @Before void setUp() { 
       def service = mockFor(SpringSecurityService)
       service.demand.encodePassword(1..2) { a -> return 'd3jk3j4ls234'}
       def control = service.createMock()
       SecUser.springSecurityService = control
   }

不确定我做错了什么,甚至我什至可以用瞬态属性做这样的事情?

【问题讨论】:

    标签: grails grails-2.0


    【解决方案1】:

    可能是模拟情况,看看这是否有效:

    @Before void setUp() { 
        def service = mockFor(SpringSecurityService)
        // using the groovy MetaClass runtime
        service.metaclass.encodePassword = {def a -> 'd3jk3j4ls234'}
        SecUser.springSecurityService = service
    }
    

    或更静态的解决方案:

    @Before void setUp() { 
        secUser.springSecurityService = [
            encodePassword : {def a -> 'd3jk3j4ls234'}
        ] as SpringSecurityService
    }
    

    【讨论】:

    • 通过一些调整,您的解决方案还修复了找不到方法,但覆盖服务方法仍然不起作用,我得到“无法在空对象上获取方法”,因为模拟服务为空。
    【解决方案2】:

    您正在尝试将模拟的springSecurityService 分配给SecUser (就好像它是一个静态的),当它是一个实例变量时它将不起作用。我不是新 Grails 2 测试注释方面的专家,但我相信如果您更换了

    SecUser.springSecurityService = control
    

    SecUser.metaClass.getSpringSecurityService = {-> control}
    

    那么它应该做你想做的事。

    【讨论】:

    • Ian,感谢您的回复,通过您的解决方案,我可以获得服务,但仍然无法模拟它。似乎我无法模拟 springsecurityservice encodepassword 方法。
    • 也许这两个答案的组合然后 - SecUser.metaClass.getSpringSecurityService = {-> [ encodePassword: {a -> 'fixedvalue'} ] }
    猜你喜欢
    • 1970-01-01
    • 2017-09-11
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2011-07-20
    • 2017-12-01
    • 1970-01-01
    相关资源
    最近更新 更多