Spock中最终类的模拟实例在测试和开发代码中的行为有所不同

时间:2019-01-14 11:13:00

标签: java javafx groovy webview spock

在我的JavaFX应用程序中,我正在使用Spock和Groovy进行测试。 我专门使用WebBrowserController来照顾我的JavafX WebView组件。我想测试一些功能,这些功能取决于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,而且还使用了包装的值之间)。

总结一下:为什么完全相同的对象会根据其调用方法的位置而表现不同?

1 个答案:

答案 0 :(得分:1)

因为GroovyMockGroovySpyGroovyStub仅对Groovy类起作用。当被Java类调用时,它们的行为类似于普通的Spock模拟。记录在here中:

  

提示

     

什么时候应该比常规的模仿更喜欢Groovy的模仿?当使用Groovy编写规范下的代码并且需要某些独特的Groovy模拟功能时,应使用Groovy模拟。 当从Java代码中调用Groovy模拟时,其行为类似于常规模拟。 请注意,不必仅仅因为规范和/或模拟下的代码而使用Groovy模拟类型是用Groovy编写的。除非您有具体的理由使用Groovy模拟,否则请选择常规模拟。