单元测试控制器时无法模拟 Grails 服务方法 - MissingMethodException

Posted

技术标签:

【中文标题】单元测试控制器时无法模拟 Grails 服务方法 - MissingMethodException【英文标题】:Unable to mock Grails Service method when unit testing Controller - MissingMethodException 【发布时间】:2014-10-11 08:55:53 【问题描述】:

在测试控制器时收到以下错误消息 - 请参阅下面的代码。 我该如何纠正这个? 当我从控制器(运行应用程序)调用服务方法时,它工作正常。

例外:

groovy.lang.MissingMethodException:没有方法签名: grails.test.GrailsMock.isOk() 适用于参数类型: (java.lang.String) 值:[H] at ...VControllerSpec.test 一些东西(VControllerSpec.groovy:)

类:VControllerSpec

import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(VController)
@Mock(VService)
class VControllerSpec extends Specification 

    void "test something"() 
        given:
        def vServiceMock = mockFor(VService)
        vServiceMock.demand.isOk  String yeah -> return true 
        controller.vService = vServiceMock.createMock()

        when:
        def isO = vServiceMock.isOk("H") 

        then:
        isO == true     
    

类:VService

import grails.transaction.Transactional

@Transactional
class VService 
    def isOk =  String yeah ->     
        def isO = false
        return isO
    

谢谢, 史蒂夫

【问题讨论】:

你在这里测试什么vServiceMock.isOk("H")?控制器动作在哪里测试? 【参考方案1】:

假设VController 中有一个动作:

def myAction() 
    vService.isOk('Hello')

下面的测试应该通过

void 'test service'() 
    given:
    def vServiceMock = mockFor(FormatService)
    vServiceMock.demand.isOk  String yeah -> return true 
    controller.vService = vServiceMock.createMock()

    when:
    def isO = controller.myAction() 

    then:
    isO == true

这里几乎没有什么需要优化的地方,包括使用方法 isOk 而不是闭包作为最佳实践。

【讨论】:

【参考方案2】:

不应测试正在模拟的方法。当我们模拟一个方法时,我们只是假设它的实现是正确的并且已经过测试(在其他一些单元测试中)。模拟的目的是将我们的测试重点限制在有限的代码行上(通常是一种方法),在您的情况下是您的控制器操作。所以上面的测试用例可以写成:

假设你的动作是这样的:

def myAction()
 [iso: vServiceMock.isOk()] // assuming isOk returns boolean true


void "test myAction"() 
        given:
        def vServiceMock = mockFor(VService)
        vServiceMock.demand.isOk  String yeah -> return true 
        controller.vService = vServiceMock.createMock()

        when:
        def model = controller.myAction() 

        then:
        model.iso   //you can skip comparison with true 
    

【讨论】:

以上是关于单元测试控制器时无法模拟 Grails 服务方法 - MissingMethodException的主要内容,如果未能解决你的问题,请参考以下文章

Grails 单元测试问题

您如何在 grails 2.3 中测试服务或控制器方法

在 Grails 单元测试中注入服务

Grails Spock单元测试需要模拟事务管理器

如何在 Grails 单元测试中使用 Spock 模拟 passwordEncoder

在 grails 控制器中模拟命令对象导致 hasErrors() 无论如何都返回 false !请帮忙