Grails:我如何模拟测试中可能在内部调用的类的其他方法

Rit*_*yak 19 testing tdd grails groovy mocking

我正在类似于下面给出的服务类中为methodA()编写测试.

Class SampleService {
  def methodA(){
     methodB()
  }

  def methodB(){
  }
}
Run Code Online (Sandbox Code Playgroud)

当我测试methodA()时,我需要能够在测试methodA()时模拟对methodB()的调用.我使用的是版本2.0.x的grails.在1.3.x发行版中,我会写一个像这样的自我模拟

def sampleServiceMock = mockFor(SampleService) 
sampleServiceMock.demand.methodB { -> } 
Run Code Online (Sandbox Code Playgroud)

但这在2.0.x版本中不起作用.我想知道在测试methodA()时模拟methodB()的其他方法是什么

Ted*_*eid 36

对于这种问题,我实际上避免了模拟并使用内置的groovyProxy能力将闭包映射作为代理对象.这为您提供了一些覆盖了一些方法的实例,但其他方法则传递给了真正的类:

class SampleService {
    def methodA() {
        methodB()
    }

    def methodB() {
        return "real method"
    }
}

def mock = [methodB: {-> return "mock!" }] as SampleService

assert "mock!" == mock.methodA()
assert "real method" == new SampleService().methodA()
Run Code Online (Sandbox Code Playgroud)

我喜欢它只更改一个实例,可以在一行中完成,并且不会混淆那个需要清理的实例之外的元类.

  • 是的,这似乎是一种模仿行为的好方法.我仍然怀念使用grails'moldFor()自我模拟的能力:( (2认同)

Art*_*ero 12

Groovy有许多嘲弄的替代方案.你可以看到Groovy Mocks的一些文档,使用Maps和Expandos代替Mocks使用Closures而不是Mocks.

在您的示例中,我将使用Groovy的元编程功能.

void testMethodA() {
    service = new SampleService()
    service.metaClass.methodB = { -> return "what you want" }
    service.methodA()
    assert "your condition"
}
Run Code Online (Sandbox Code Playgroud)

  • 我终于用这种方法来嘲笑.但是,从语义上讲,更改类的签名以进行测试通过似乎极端:) (2认同)