Spock中最终类的模拟实例在测试和开发代码中的行为有所不同 [英] Mocked instance of final class in Spock behaves differently in test and dev code

查看:108
本文介绍了Spock中最终类的模拟实例在测试和开发代码中的行为有所不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的JavaFX应用程序中,我正在使用Spock和Groovy进行测试. 我有专用的WebBrowserController来照顾我的JavafX WebView组件.我想测试一些功能,这些功能取决于WebView的当前位置和文档.

In my JavaFX application I am using Spock and Groovy for testing. I have dedicated WebBrowserController for taking care of my JavafX WebView component. I wanted to test some functionalities that depend on current Location and Document of the WebView.

WebBrowserController的相关部分:

Relevant part of WebBrowserController:

public WebEngine getEngine() {
    return panel.getWebView().getEngine();
}

这是我为测试创建WebBrowserController实例的方式. 请注意,我在这里使用的GroovyMock-普通Mock(...)不适用于最终课程,WebEngine是最终课程.

This is how I create an instance of WebBrowserController for my tests. Notice the GroovyMock I used there - ordinary Mock(...) does not work for final classes and WebEngine is a final class.

WebBrowserController getMockedControllerWithDocument(Document document) {
    WebBrowserController controller = Mock(WebBrowserController)
    controller.getEngine() >> GroovyMock(WebEngine) {
        getDocument() >> document
        getLocation() >> "some random string"
    }

    controller
}

下面的行正在测试中,并且断了.我希望会返回一些随机字符串",但我只是通过了失败的测试和NPE.

The line below is under the test and it breaks. I would expect "some random string" to be returned but I just get failed test and NPE.

String url = controller.get().getEngine().getLocation()

现在有趣的部分-我已经在两个地方检查了WebEngine的实例-在getMockedControllerWithDocument的末尾和上面粘贴的行.我发现它引用了相同的对象.但是,当我在测试代码之外调用任何存根方法时,我都被NPE击中-getLocation()执行了实际的实现,而不是存根(原始方法不仅是简单的getter,而且使用介于两者之间的包装值)

Now the interesting part - I have examined the instance of WebEngine in two places - at the end of getMockedControllerWithDocument and at the line pasted above. What I found out is that it referenced the same object. Yet, when I invoked any of the stubbed methods outside of test code I was hit by NPE - getLocation() executed the actual implementation and not the stub (the original method is not just a simple getter and it uses a wrapped value in between).

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

Summing it up: why the hell does the exact same object behaves differently depending on the place its methods are being invoked?

推荐答案

因为GroovyMockGroovySpyGroovyStub仅对Groovy类起作用.当被Java类调用时,它们的行为类似于普通的Spock模拟. 此处:

Because GroovyMock, GroovySpy and GroovyStub only work as you expect for Groovy classes. When called by Java classes, they behave like normal Spock mocks. This is documented here:

提示

什么时候应该比常规的模仿更喜欢Groovy的模仿?当规范下的代码用Groovy编写并且需要某些独特的Groovy模拟功能时,应使用Groovy模拟. 从Java代码调用时,Groovy模拟将表现得像普通模拟一样. 类型是用Groovy编写的.除非您有具体的理由使用Groovy模拟,否则请选择常规模拟.

TIP

When Should Groovy Mocks be Favored over Regular Mocks? Groovy mocks should be used when the code under specification is written in Groovy and some of the unique Groovy mock features are needed. When called from Java code, Groovy mocks will behave like regular mocks. Note that it isn’t necessary to use a Groovy mock merely because the code under specification and/or mocked type is written in Groovy. Unless you have a concrete reason to use a Groovy mock, prefer a regular mock.

这篇关于Spock中最终类的模拟实例在测试和开发代码中的行为有所不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆