Closed GoogleCodeExporter closed 9 years ago
Are there any configurations of Grails to include all classes in gmock's jar
file? The hard coded whitelist sounds like an ugly solution to me.
Original comment by JohnnyJianHY
on 22 Mar 2014 at 1:42
It is possible to disable forked execution by setting grails.project.fork.test
to false. In that case, the build dependencies are mixed with the test (and I
guess compile and runtime) dependencies in a GrailsRootLoader classloader. I
also think the build dependencies are not cherry-picked in this case.
Obviously, in this case, gmock work fine.
But forked execution is the new default in Grails and it's recommended to use
for several reasons (see
http://grails.io/post/43484836985/road-to-grails-2-3-forked-execution ). If
it's not possible to make gmock work out-of-the-box with forked execution, I
think at least there should be a way to make it use the context classloader or
to be able to specify the classloader to be used (perhaps globally in the
GMockController).
Original comment by contrate...@gmail.com
on 22 Mar 2014 at 2:39
It sounds more like an issue of grails instead of gmock to me. Don't you think
so?
Original comment by JohnnyJianHY
on 22 Mar 2014 at 4:53
IMHO, Grails should allow you more control over the -classpath Classloader (it
should put all build dependencies there). If it did, we could make gmock a
build dependency and everything would work.
This doesn't mean that gmock doesn't have a deficiency here. The fact is that,
depending o which classloader gmock was loaded, some classes will be
unmockable. It should have some mechanism (e.g. using the somewhat crude
mechanism of the context classloader) to go around these kinds of problems.
This is not specific to Grails. You can test this problem with a script like
this:
#!/usr/bin/groovy
def cl = new URLClassLoader(
[new URL('file:/home/glopes/.m2/repository/org/gmock/gmock/0.8.3/gmock-0.8.3.jar')] as URL[],
getClass().classLoader ?: ClassLoader.systemClassLoader)
def gmockControllerClass = cl.loadClass('org.gmock.GMockController', true)
Thread.currentThread().contextClassLoader = cl //doesn't help
def gmockController = gmockControllerClass.newInstance()
gmockController.mock(gmockControllerClass) //works fine because it was loaded
by cl
gmockController.mock(Closure) //fails: ClassNotFoundException:
org.gmock.internal.cglib.proxy.Factory
Original comment by contrate...@gmail.com
on 22 Mar 2014 at 10:47
You've got a point there.
I was wondering why there is a ClassNotFoundException, so I took a look into
the code of cglib. It turns out that cglib uses Closure's classloader to load
the generated class which refers the Factory class of cglib (which is loadded
by the classloader of gmock that you provided). The classloader of Closure is
the parent of the classloader of gmock, so of course it doesn't know the
classes of gmock.
Of course gmock can make sure cglib uses the classloader of gmock, but what if
the class under mock and gmock use two separated classloaders (no hierarchical
relationship)? I don't think cglib support that.
To deal with this situation, gmock needs to catch this exception and when it
does catch one, it should give up using cglib and only modify the metaclass of
the class under mock.
Original comment by JohnnyJianHY
on 23 Mar 2014 at 4:15
@contratempo, it is fixed on the trunk, please give it a try.
Original comment by JohnnyJianHY
on 12 Apr 2014 at 7:56
Works for me in trunk. Any ETA about the release?
I don't want to build it myself :)
Original comment by mauro.ci...@cymait.com
on 24 Aug 2014 at 11:49
Original issue reported on code.google.com by
contrate...@gmail.com
on 21 Mar 2014 at 12:04Attachments: