如何在Groovy中重置模拟静态方法?

如何在Groovy中重置模拟静态方法?,groovy,Groovy,我在测试设置中有以下内容: def originalPostAsXml = RestClient.&postAsXml RestClient.metaClass.'static'.postAsXml = { String uriPath, String xml -> return 65536 } 在测试清理中: RestClient.metaClass.'static'.postAsXml = originalPo

我在测试设置中有以下内容:

    def originalPostAsXml = RestClient.&postAsXml

    RestClient.metaClass.'static'.postAsXml = {
        String uriPath, String xml ->
        return 65536
    }
在测试清理中:

    RestClient.metaClass.'static'.postAsXml = originalPostAsXml
但是,当下一个测试运行时,当它尝试执行RestClient.postAsXml时,它会遇到StackOverflower错误:

at groovy.lang.Closure.call(Closure.java:282)

看起来RestClient.postAsXml递归地指向它自己。重置模拟静态方法的正确方法是什么?

上面schmolly159的提示让我找到了以下解决方案:

    def originalPostAsXml = RestClient.metaClass.getMetaMethod('postAsXml', [String, String] as Class[])
然后重置方法:

    RestClient.metaClass.'static'.postAsXml = { String uriPath, String xml ->
        originalPostAsXml.invoke(delegate, uriPath, xml)
    }

在单元测试中,我经常在
tearDown()
中将元类设置为
null
,这似乎允许类在没有修改的情况下像最初那样工作

例如:

void setUp() {
    super.setUp()
    ServerInstanceSettings.metaClass.'static'.list = {
        def settings = [someSetting:'myOverride'] as ServerInstanceSettings
        return [settings]
    }
}

void tearDown() {
    super.tearDown()
    ServerInstanceSettings.metaClass.'static'.list = null
}

如果您使用的是JUnit4,那么在这种情况下,您可以使用
@AfterClass
,这可能更有意义。

我发现简单地设置
.metaClass=null
对我来说很有用

斯波克示例:

def "mockStatic Test"(){
  given:
  RestClient.metaClass.static.postAsXml = {
    String uriPath, String xml ->
    return 65536
  }

  when:
  //some call that depends on RestClient.postAsXml

  then:
  //Expected outcomes

  cleanup:
  //reset metaclass
  RestClient.metaClass = null
}

这里有一个类似的问题:您可以重置元类-看到这个问题,它有答案,谢谢-我也在使用Spock,并将Class.metaclass.static.方法设置为null不起作用,但将Class.metaclass设置为null起作用。