【问题标题】:Injecting a mock service into a domain class for a Grails unit test?将模拟服务注入域类以进行 Grails 单元测试?
【发布时间】:2013-08-08 17:31:11
【问题描述】:

我正在 Grails 2.1.1 下编写一些基于 Spock 规范的单元测试。我无法将springSecurityService 注入到我的单位使用的域对象中。

这是我目前所拥有的,

@Mock([SecUser])
@TestFor(FooService)
class FooServiceSpec extends Specification {

    def "test some stuff"() {
        given:
        def mockSecUserService = Mock(SecUserService)
        mockSecUserService.emailValid(_) >> { true }
        mockSecUserService.checkUsername(_) >> { null }
        service.secUserService = mockSecUserService

        def mockSpringSecurityService = Mock(SpringSecurityService)
        mockSpringSecurityService.encodePassword(_) >> { 'tester' }
        // FIXME this needs to be injected somehow

        def params = [
                email: 'unittest@test.com',
                username: 'unittester',
                password: 'tester',
                password2: 'tester'
        ]

        when:
        def result = service.createUser(params)

        then:
        // test results
    }
}

所以发生的情况是我的服务被测试抛出 NullPointerException 因为 mockSpringSecruityService 没有注入。我的服务中的 createUser 调用验证了一些参数,然后创建了一个 SecUser 域对象。

SecUser 注入了以下服务以支持密码编码,

class SecUser {
    transient springSecurityService

我想不通的是以域类可用的方式注入此服务。我知道已经有一些与此主题相关的帖子,但其中大多数假设测试可以实例化域对象,但在我的例子中,实例化是正在测试的单元的一部分。

我已尝试以下方法代替 FIXME,

defineBeans {
    mockSpringSecurityService(SpringSecurityService) { bean -> 
        bean.autowire = true
    }
}

但是结果我得到了跟随错误,

| groovy.lang.MissingMethodException:没有方法签名: grails.plugins.springsecurity.SpringSecurityService.call() 是 适用于参数类型:(java.lang.Class, Skillz.GameAccountServiceSpec$_spock_feature_0_0_closure4_closure5) 值:[类 grails.plugins.springsecurity.SpringSecurityService, ...] 可能的解决方案:wait()、any()、find()、dump()、collect()、 grep()

有什么想法吗?

【问题讨论】:

  • 您是否也尝试过使用元类?喜欢SecUser.metaClass.springSecurityService = mockSpringSecurityService。顺便说一句,def springSecurityService 也可以用来代替transient springSecurityService 我猜。 (默认情况下,在域类中任何类型为 def 的东西都应该是瞬态的)
  • 你能试试this similar way吗?但这并不能帮助我解决问题。
  • @dmahapatro,是的,那是我尝试过的众多文章之一,但我认为那篇文章是针对旧的圣杯的。我对元类方法有一些运气,我很快就会发布一些东西。

标签: unit-testing testing grails groovy spock


【解决方案1】:

我最终做的是,

SecUser.metaClass.encodePassword = { null }

在我的域对象中encodePassword 是使用springSecurityService bean 的方法。所以如果我理解正确的话,这只是覆盖这个方法什么都不做(这个方法是无效的)。

我更喜欢使用 metaClass 来伪造注入 bean,但我的尝试

SecUser.metaClass.getSpringSecurityService = { mockSpringSecurityService }

encodePassword 尝试使用 SpringSecurityService 时出现 NPE。

我觉得这是一个不太理想的解决方法,所以我希望有人能给出一个不那么生硬的答案。

【讨论】:

  • 这是我同意的绕过方式。我不想给出这个答案。如果你已经模拟了 springSecurityService,那么在元类 encodePassword 中使用模拟对象。像SecUser.metaClass.encodePassword = {-> mockSpringSecurityService.encodePassword } 这样的东西,因为它已经被模拟为tester,如问题所示。
猜你喜欢
  • 2016-09-05
  • 1970-01-01
  • 2016-01-31
  • 2012-08-31
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
相关资源
最近更新 更多