在类的所有实例方法中隐式使用Groovy Category

时间:2011-04-05 12:56:47

标签: groovy metaprogramming categories metaclass

我有简单的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,因此我不必指定{{ 1}}在每种方法中。

有可能吗?

2 个答案:

答案 0 :(得分:11)

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

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

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

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

答案 1 :(得分:1)

现在您可以选择使用扩展模块而不是类别: 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不会识别它。