【问题标题】:Use Groovy Category implicitly in all instance methods of class在类的所有实例方法中隐式使用 Groovy Category
【发布时间】:2011-07-29 23:02:06
【问题描述】:

我有一个简单的 Groovy 类别类,它向 String 实例添加方法:

final class SampleCategory {

    static String withBraces(String self) {
        "($self)"
    }

}

我想在我的单元测试中使用这个类别(例如)。它看起来像这样:

class MyTest {
    @Test
    void shouldDoThis() {
        use (SampleCategory) {
            assert 'this'.withBraces() == '(this)'
        }
    }

    @Test
    void shouldDoThat() {
        use (SampleCategory) {
            assert 'that'.withBraces() == '(that)'
        }
    }
}

然而,我想要实现的是能够指定 SampleCategory 类别在 MyTest 的每个实例方法的范围内使用,因此我不必在每个方法中指定 use(SampleCategory) { ... } .

有可能吗?

【问题讨论】:

  • 应该可以使用 AST 转换,但不知道如何实现它。用户指南here 中有一个部分,Hamlet D'arcy 在他的"Code generation on the JVM"-talk 中谈到了它(不确定他有多深入)。祝你好运!
  • 谢谢你的想法!听起来像是一个不错的小型 OSS 项目候选人 :)

标签: groovy metaprogramming categories metaclass


【解决方案1】:

您可以使用 mixin 将类别直接应用于 String 的元类。将 null 分配给 metaClass 以将其重置为 groovy 默认值。例如:

@Before void setUp() { 
    String.mixin(SampleCategory)
}

@After void tearDown() {
    String.metaClass = null
}

@Test
void shouldDoThat() {
    assert 'that'.withBraces() == '(that)'
}

【讨论】:

  • 你真的试过了吗?我想出了一个几乎相同的解决方案,并对其进行了测试,但没有奏效。
  • ataylor,谢谢,解决方案确实有效,而且非常优雅!我做了几个小改动(例如使用@BeforeClass/@AfterClass)
  • 太好了,我想有比进行自定义 AST 编程更简单的方法 :) 感谢您的提示!
【解决方案2】:

现在您可以选择使用扩展模块而不是类别: http://mrhaki.blogspot.se/2013/01/groovy-goodness-adding-extra-methods.html

从好的方面来说,Intellij 会识别扩展。我刚刚注意到它甚至不需要是链接建议的单独模块,只需将 META-INF/services/org.codehaus.groovy.runtime.ExtensionModule 添加到项目中:

# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = module
moduleVersion = 1.0
extensionClasses = SampleExtension

扩展类的定义与普通类别非常相似:

class SampleExtension {
    static String withBraces(String self) {
        "($self)"
    }
}

可以这样使用:

def "Sample extension"() {
    expect: 'this'.withBraces() == '(this)'
}

如果您使用的是 Spock,则可以在规范中使用 @Use 注释。这样做的缺点是 Intellij 无法识别它。

【讨论】:

    猜你喜欢
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 2016-11-11
    • 2018-06-08
    • 1970-01-01
    • 2015-07-29
    相关资源
    最近更新 更多