【发布时间】:2020-04-15 23:11:44
【问题描述】:
当我们将someClass.metaClass.constructor 用于在带有@CompileStatic 注释的类的方法中可用的任何特定类(如RESTClient)时,构造函数覆盖根本不起作用。
当我们删除 @CompileStatic 注释时,它可以正常工作。我错过了什么吗?
示例代码:
@CompileStatic
class FooClass {
String getDataFromProvider() {
String url = "https://www.example.com"
RESTClient restClient = new RESTClient(url)
HttpResponseDecorator response = restClient.post([:]) as HttpResponseDecorator
return response
}
}
还有测试用例:
import groovyx.net.http.HttpResponseDecorator
import groovyx.net.http.RESTClient
import spock.lang.Specification
class FooContentSpec extends Specification {
void "test getDataFromProvider method"() {
given: "Rest url"
String restURL = "https://www.example.com"
and: "Mock RESTClient"
RESTClient mockedRestClient = Mock(RESTClient)
// THIS IS NOT WORKING
RESTClient.metaClass.constructor = { Object url ->
assert restURL == url
return mockedRestClient
}
mockedRestClient.metaClass.post = { Map<String, ?> args ->
return ""
}
when: "We hit the method"
HttpResponseDecorator response = Content.getDataFromProvider()
then: "We should get status 200"
response.statusCode == 200
}
}
根据Groovy Lang 文档:
MockFor和StubFor不能用于测试静态编译的类,例如使用@CompileStatic的 Java 类或 Groovy 类。要存根和/或模拟这些类,您可以使用 Spock 或 Java 模拟库之一。
预期行为
在这种情况下,RESTClient 的构造函数覆盖应该在我们的测试用例中起作用,因为我们不想在每个测试用例中都访问第三方 API。
实际行为
不幸的是,RESTClient 没有被嘲笑,因为 @CompileStatic 注释每次都会命中 API。
环境信息
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Groovy: 2.4.10,
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015,
JVM: 1.8.0_221 (Oracle Corporation 25.221-b11),
OS: Mac OS X 10.15.2 x86_64
【问题讨论】:
标签: java unit-testing groovy metaprogramming spock