在我的JavaFX应用程序中,我使用Spock和Groovy进行测试。我有专门的WebBrowserController
来处理我的JavafXWebView
组件。我想测试一些依赖于WebView
当前位置和文档的功能。
WebBrowserController的相关部分:
public WebEngine getEngine() {
return panel.getWebView().getEngine();
}
这就是我为测试创建WebBrowserController
实例的方式。注意,我在那里使用的GroovyMock
——普通的Mock(...)
不适用于最终类,而WebEngine
是最终类。
WebBrowserController getMockedControllerWithDocument(Document document) {
WebBrowserController controller = Mock(WebBrowserController)
controller.getEngine() >> GroovyMock(WebEngine) {
getDocument() >> document
getLocation() >> "some random string"
}
controller
}
下面的线正在测试中,它断了。我希望返回"一些随机字符串",但我只是得到了失败的测试和NPE。
String url = controller.get().getEngine().getLocation()
现在有趣的部分——我在两个地方检查了WebEngine
的实例——在getMockedControllerWithDocument
的末尾和上面粘贴的行。我发现它引用了同一个对象。然而,当我在测试代码之外调用任何存根方法时,我被NPE击中了——getLocation()
执行了实际的实现,而不是存根(原始方法不仅仅是一个简单的getter,它在两者之间使用了一个包装值)。
总结一下:为什么完全相同的对象的行为会因其方法被调用的位置而异?
因为GroovyMock
、GroovySpy
和GroovyStub
只能按照Groovy类的预期工作。当Java类调用时,它们的行为就像普通的Spock mock。这里记录了这一点:
TIP
Groovy Mock什么时候应该比常规Mock更受欢迎?当规范下的代码是用Groovy编写的,并且需要一些独特的Groovy mock功能时,应该使用Groovy mock当从Java代码调用时,Groovy mock的行为将类似于常规mock注意,不必仅仅因为规范和/或mock类型下的代码是用Groovy编写的,就使用Groovy mock。除非您有具体的理由使用Groovy mock,否则最好使用常规的mock。