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

时间:2011-12-01 22:15:35

标签: groovy

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

    def originalPostAsXml = RestClient.&postAsXml

    RestClient.metaClass.'static'.postAsXml = {
        String uriPath, String xml ->
        return 65536
    }

并在测试清理中:

    RestClient.metaClass.'static'.postAsXml = originalPostAsXml

但是当下一个测试运行时,当它尝试执行RestClient.postAsXml时,它会遇到StackOverflowError:

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

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

3 个答案:

答案 0 :(得分:6)

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

示例:

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,这可能更有意义。

答案 1 :(得分:2)

我发现简单地设置<Class>.metaClass = null对我有用。

Spock示例:

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
}

答案 2 :(得分:1)

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

    def originalPostAsXml = RestClient.metaClass.getMetaMethod('postAsXml', [String, String] as Class[])

然后重置方法:

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