1

我有两个班级:

class Foo {
    String doSomething(String a, String b) {
        return 'Not Working'
    }
}


class Bar {
    String methodIWannaTest() {
        return new Foo().doSomething('val1', 'val2')
    }
}

我想在测试中替换“doSomething”,但它不起作用

class BarTests {
    @Test
    void testMethodIWannaTest() {
        Foo.metaClass.doSomething {String a, String b -> return 'Working'}

        assert new Bar().methodIWannaTest() == 'Working' //THIS TEST FAIL, return 'Not Working'
    }
}

*我知道测试并没有真正的意义,这只是为了表明我的观点

我做错了什么?不使用 'mockFor' 是否可以做到这一点?

4

4 回答 4

1

我发现了问题:

首先,在我的例子中,我在定义闭包时忘记了“=”

Foo.metaClass.doSomething {String a, String b -> return 'Working'}

应该

Foo.metaClass.doSomething = {String a, String b -> return 'Working'}

在搜索时,我还发现您不能用闭包替换带有可选参数的方法。应该是bug

于 2013-05-28T12:44:44.630 回答
1

我建议你重新开始测试。Baby Steps是我遵循的。:)

  • 创建一个新的 grails 应用程序。
  • 在包下创建FooBar内部src/groovy
  • 从命令提示符创建单元测试用例。放置所需的测试代码。
  • 执行grails test-app

[Grails v2.2.0]

于 2013-05-23T14:17:26.473 回答
1

另一种选择是使用Groovy MockFor

def mock = MockFor(Foo)
mock.demand.doSomething = {String a, String b -> return 'Working'}
mock.use {
  assert new Bar().methodIWannaTest() == 'Working'
}

缺点是有一个错误,使单元测试无法清除模拟。这在 2.2.3 中是固定的。

于 2013-05-23T14:57:14.513 回答
0

我在GGTS 3.2.0上进行了尝试,得到了以下结果。

复制所有代码并在 Grails 2.2.2 上运行:一切正常。但是,然后我注释掉了Foo.metaClass.doSomething = {String a, String b -> return 'Working'}一行,令人惊讶的是,测试仍然成功通过。我做了更多更改,而 metaClass 似乎只是在测试之间“缓存”了:更改没有效果。

然后我想如果 Grails 有可能在交互模式下运行。转到Preferences > Groovy > Grails > Grails Launch并找到一个复选框“保持外部 Grails 运行”打勾。它的工具提示甚至有以下文字:“警告:实验性功能!”。取消选中该复选框就可以了,并且元类不再在测试运行之间被缓存。我仍然想知道为什么默认情况下会打开一个实验功能......

于 2013-05-23T18:29:01.110 回答