我有一个POJO,它使用服务来做一些事情:
public class PlainOldJavaObject {
private IService service;
public String publicMethod(String x) {
return doCallService(x);
}
public String doCallService(String x) {
if(service == null) {
throw new RuntimeException("Service must not be null");
}
return service.callX(x);
}
public interface IService {
String callX(Object o);
}
}我有一个Groovy测试用例:
class GTest extends GroovyTestCase {
def testInjectedMockIFace() {
def pojo = new PlainOldJavaObject( service: { callX: "very groovy" } as IService )
assert "very groovy" == pojo.publicMethod("arg")
}
def testMetaClass() {
def pojo = new PlainOldJavaObject()
pojo.metaClass.doCallService = { String s ->
"no service"
}
assert "no service" == pojo.publicMethod("arg")
}
}第一个测试方法testInjectedMockIFace按预期工作: POJO是用IService的动态实现创建的。当调用callX时,它只返回"very groovy“。这样,服务就被模拟出来了。
但是,我不明白为什么第二种方法testMetaClass不能像预期的那样工作,而是在尝试调用服务对象上的callX时抛出NullPointerException。我以为我已经用下面这行代码重写了doCallService方法:
pojo.metaClass.doCallService = { String s ->我做错了什么?
谢谢!
发布于 2010-03-09 04:12:52
你的语法有点不对劲。问题是pojo是一个Java对象,没有metaClass。要使用ExpandoMetaClass拦截对PlainOldJavaObject的doCallService的调用:
只需替换:
pojo.metaClass.doCallService = { String s ->
"no service"
}通过以下方式:
PlainOldJavaObject.metaClass.doCallService = { String s ->
"no service"
}发布于 2009-12-29 04:59:55
如果您的POJO确实是一个Java类,而不是Groovy类,那么这就是您的问题所在。Java类不通过metaClass调用方法。例如,在Groovy中:
pojo.publicMethod('arg')等同于这个Java:
pojo.getMetaClass().invokeMethod('publicMethod','arg');invokeMethod通过metaClass发送呼叫。但是这个方法:
public String publicMethod(String x) {
return doCallService(x);
}是一种Java方法。它不使用invokeMethod来调用doCallService。要让您的代码正常工作,PlainOldJavaObject需要是一个Groovy类,这样所有调用都将通过metaClass。普通的Java代码不使用metaClasses。
简而言之:即使Groovy也不能覆盖Java方法调用,它只能覆盖来自Groovy或通过invokeMethod调度的调用。
发布于 2009-12-18 20:21:54
你所拥有的看起来很好。我在groovy控制台webapp上运行了一个稍微修改过的版本,它运行起来没有任何问题。您可以在http://groovyconsole.appspot.com/上亲自查看使用此代码。
public interface IService {
String callX(Object o);
}
public class PlainOldJavaObject {
private IService service;
public String publicMethod(String x) {
return doCallService(x);
}
public String doCallService(String x) {
if(service == null) {
throw new RuntimeException("Service must not be null");
}
return service.callX(x);
}
}
def pojo = new PlainOldJavaObject()
pojo.metaClass.doCallService = { String s ->
"no service"
}
println pojo.publicMethod("arg")您使用的是什么版本的Groovy。这很可能是Groovy的元类实现中的一个bug。groovy语言的发展非常迅速,元类实现也因版本而异。
编辑-来自评论的反馈:
groovy控制台webapp的版本是1.7-rc-1。所以看起来这个版本可能会像你想要的那样工作。他们目前在RC2中,所以我预计它很快就会发布。不确定您看到的是错误还是1.6.x版本中工作方式的不同。
https://stackoverflow.com/questions/1927796
复制相似问题