Groovy Mocking a Method That Exists on Object

March 22, 2012 - 1 minute read -
orm groovy mock-objects jpa

In Groovy, the find method exists on Object. The find method is also an instance method on EntityManager which is commonly used in JPA to get an instance based on a database id. I was trying to create a Mock of EntityManager like:

def emMock = new MockFor(EntityManager)
emMock.demand.find { Class clazz, Object rquid -> return new Request(rqUID: rquid) }
def em = emMock.proxyDelegateInstance()

This gave me an error though: groovy.lang.MissingMethodException: No signature of method: com.onelinefix.services.RequestRepositoryImplTest$_2_get_closure1.doCall() is applicable for argument types: (groovy.mock.interceptor.Demand) values: [groovy.mock.interceptor.Demand@a27ebd9] Possible solutions: doCall(java.lang.Class, java.lang.Object), findAll(), findAll(), isCase(java.lang.Object), isCase(java.lang.Object) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) ~[groovy-all-1.8.6.jar:1.8.6] at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877) ~[groovy-all-1.8.6.jar:1.8.6] at groovy.lang.Closure.call(Closure.java:412) ~[groovy-all-1.8.6.jar:1.8.6] at groovy.lang.Closure.call(Closure.java:425) ~[groovy-all-1.8.6.jar:1.8.6] It ends up that find is a DefaultGroovyMethod that's added to all Objects and this was causing the mock.demand to get confused because it thought I was trying to call the Object.find.

Luckily there is a workaround and that's to use the ordinal argument for find.

emMock.demand.find(1) { Class clazz, Object rquid -> return new Request(rqUID: rquid) }

That's enough of a change to invoke mock version instead of the DefaultGroovyMethod version. Now if I only knew why....