在类的所有实例方法中隐式使用 Groovy Category
Posted
技术标签:
【中文标题】在类的所有实例方法中隐式使用 Groovy Category【英文标题】:Use Groovy Category implicitly in all instance methods of class 【发布时间】: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 项目候选人 :) 【参考方案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 无法识别它。
【讨论】:
以上是关于在类的所有实例方法中隐式使用 Groovy Category的主要内容,如果未能解决你的问题,请参考以下文章