funbee / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

Mockito does not work in eclipse plugins #11

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Unzip Eclipse project (attachment)
2. Run MockitoTest as JUnit Test
3. Run MockitoTest as JUnit Plugin Test 

What is the expected output? What do you see instead?
When trying to mock an eclipse interface, an exception is thrown. Mocking
Java classes or classes from the same plugin, (or an buddy plugin) works.

What version of the product are you using? On what operating system?
mockito 1.3, Eclipse Target 3.3.1

Please provide any additional information below.
Seems to be some class loading problems. jmock had these problems in some
old version too. EasyMock works out of the box for eclipse plugins.

Original issue reported on code.google.com by Knut.Fri...@yahoo.de on 25 Apr 2008 at 3:47

Attachments:

GoogleCodeExporter commented 9 years ago
Exception when run as JUnit Test:

net.sf.cglib.core.CodeGenerationException:
java.lang.reflect.InvocationTargetException-->null
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.mockito.internal.creation.MockFactory.createMock(MockFactory.java:29)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:24)
    at org.mockito.Mockito.mock(Mockito.java:274)
    at MockitoTest.testMockito(MockitoTest.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at junit.framework.TestCase.runTest(TestCase.java:164)
    at junit.framework.TestCase.runBare(TestCase.java:130)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.runTest(TestSuite.java:230)
    at junit.framework.TestSuite.run(TestSuite.java:225)
    at
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestR
eference.java:130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:460)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.jav
a:196)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
    ... 24 more
Caused by: java.lang.SecurityException: class
"org.eclipse.core.databinding.observable.map.IMapChangeListener$$EnhancerByCGLIB
$$e1a71500"'s
signer information does not match signer information of other classes in the 
same package
    at java.lang.ClassLoader.checkCerts(ClassLoader.java:775)
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:487)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:614)
    ... 30 more

Original comment by Knut.Fri...@yahoo.de on 25 Apr 2008 at 3:51

GoogleCodeExporter commented 9 years ago
Exception when run as Junit Plugin Test.

net.sf.cglib.core.CodeGenerationException:
java.lang.reflect.InvocationTargetException-->null
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.mockito.internal.creation.MockFactory.createMock(MockFactory.java:29)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:24)
    at org.mockito.Mockito.mock(Mockito.java:274)
    at MockitoTest.testMockito(MockitoTest.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at junit.framework.TestCase.runTest(TestCase.java:164)
    at junit.framework.TestCase.runBare(TestCase.java:130)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.runTest(TestSuite.java:230)
    at junit.framework.TestSuite.run(TestSuite.java:225)
    at
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestR
eference.java:130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:460)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at
org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginT
estRunner.java:58)
    at
org.eclipse.pde.internal.junit.runtime.CoreTestApplication.run(CoreTestApplicati
on.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at
org.eclipse.equinox.internal.app.EclipseAppContainer.callMethod(EclipseAppContai
ner.java:572)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:171)
    at
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(Ecli
pseAppLauncher.java:106)
    at
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLau
ncher.java:76)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:363)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:176)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:508)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:447)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1173)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1148)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
    ... 43 more
Caused by: java.lang.NoClassDefFoundError: net/sf/cglib/proxy/Factory
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
    ... 49 more

Original comment by Knut.Fri...@yahoo.de on 25 Apr 2008 at 3:52

GoogleCodeExporter commented 9 years ago
Looking at it...

Original comment by szcze...@gmail.com on 25 Apr 2008 at 4:03

GoogleCodeExporter commented 9 years ago
Ok, I tried with the latest Eclipse distro (3.3.2) and I am able to reproduce 
the
problem.

Original comment by szcze...@gmail.com on 25 Apr 2008 at 5:03

GoogleCodeExporter commented 9 years ago
Problem appears also in earlier versions of Mockito (tried with 1.2).

Original comment by szcze...@gmail.com on 25 Apr 2008 at 5:06

GoogleCodeExporter commented 9 years ago

Original comment by szcze...@gmail.com on 27 Apr 2008 at 2:32

GoogleCodeExporter commented 9 years ago
Ok, I'm on this bug now (a bit hung-over after my last double night out in 
London but
let's do it).

I tried both EasyMock and jmock. Only jmock works out of the box.

EasyMock works with your example only because you're mocking an interface (EM 
uses
dynamic proxies for interfaces and cglib for classes, Mockito always uses 
cglib). But
if you try to create easymock for a class from plugins (e.g: 
AbstractObservableMap),
EM breaks the same way as mockito.

Original comment by szcze...@gmail.com on 27 Apr 2008 at 3:05

GoogleCodeExporter commented 9 years ago
Fixed in trunk.
Thanks a lot for detailed description and sample code!

Snapshot build to grab here:
http://hudson.ramfelt.se/job/Mockito/lastSuccessfulBuild/artifact/trunk/target/m
ockito-all-snapshot.jar
Other snapshot builds here:
http://hudson.ramfelt.se/job/Mockito

We'll try to release it soon but it may be a week or two (I'm switching 
countries and
also there is one feature half-done that should be finished).

Original comment by szcze...@gmail.com on 27 Apr 2008 at 4:17

GoogleCodeExporter commented 9 years ago
Hmm, I tried your snapshot release, but the error still is present. Tried with 
both
JDK 5 and 6. 

I debugged your code and the
enhancer.setNamingPolicy(ALLOWS_MOCKING_CLASSES_IN_SIGNED_PACKAGES); call is
correctly invoked. 

When running the test as JUnit test I get the exception at 
        Enhancer.registerCallbacks(mockClass, new Callback[] { filter });

When running the test as JUnit plugin test I get the exception at 
        Class mockClass = enhancer.createClass();

Should I attach the exceptions? 

BTW: I'm using the org.eclipse.core.databinding;bundle-version="1.0.1" 
reference in
my plug-in.

Thanks, Ulli

Original comment by Knut.Fri...@yahoo.de on 29 Apr 2008 at 12:03

GoogleCodeExporter commented 9 years ago
Yes, please attach the stack trace.

Are you running exactly the same test as you did initially?

I'm double checking the fix...

Original comment by szcze...@gmail.com on 29 Apr 2008 at 9:40

GoogleCodeExporter commented 9 years ago
You're right, the error still exists. In my environment the newer version of 
cglib
was being picked up and that's why I thought the bug is fixed.

Looks like it was too optimistic to downgrade cglib from beta to latest stable. 
I'm
gonna have to go back to using latest cglib beta. In future I will write kill 
the
dependency to cglib and write the proxies straight with asm.

Original comment by szcze...@gmail.com on 29 Apr 2008 at 10:24

GoogleCodeExporter commented 9 years ago
Switching back to cglib beta will prevent us from releasing mockito-core to 
maven
central repository as the latest beta has never been deployed there and we 
cannot
release mockito-core with missing dependency. That's the Central upload policy.

Original comment by iczechowski@gmail.com on 30 Apr 2008 at 9:09

GoogleCodeExporter commented 9 years ago
In the short term, let's then prepare a downloadable with snapshot jar + cglib 
2.2
beta. The download doesn't have to live on the main page but it should be there 
so
that anyone who faces the problem mockito + eclipse plugins can solve it. This 
is
something I can do on Monday because earlier I don't have much time. Ulli, you 
can
wait for this download or if you are very keen on using mockito (and I hope you 
are
:), then please grab mockito snapshot core jar and use it in your environment 
with
cglib 2.2 beta jar (you can get this jar from cglib site or from zipped 
distribution
of mockito with version < 1.3). Please mind other required jars(all in zipped
distribution).

In the longer term I'm hoping to remove the dependency to cglib by implementing
proxies by hand using ASM directly. C'mon, how hard can it be? :) This is 
something
me or other contributor can do sometime later.

Original comment by szcze...@gmail.com on 3 May 2008 at 5:55

GoogleCodeExporter commented 9 years ago
I've downloaded the snapshot and the beta version. No need to prepare a special
release for me. 

Original comment by Knut.Fri...@yahoo.de on 6 May 2008 at 4:53

GoogleCodeExporter commented 9 years ago
Ok then, I'm not going to prepare a special realease.

The current plan is to try using java.lang.instrument instead of cglib for 
creating
proxies.

Original comment by szcze...@gmail.com on 7 May 2008 at 2:52

GoogleCodeExporter commented 9 years ago
java.lang.instrument is no good because it requires java to run with agent. 
Going
back to the idea of writing proxy code from scratch using ASM.

Original comment by szcze...@gmail.com on 15 May 2008 at 7:25

GoogleCodeExporter commented 9 years ago
Hi.

I run into the same problem. I've upgraded to mockito-all-snapshot.jar 
(2008.05.20).

Now I recognized another problem: 
Caused by: java.lang.SecurityException: 
class "org.osgi.framework.BundleContext$$FastClassByCGLIB$$f6f1d55f"'s signer 
information does not match signer information of other classes in the same 
package

May be it's trivial problem, but actually I can't resolve. Can you help me?

I've attached the full stack trace, a my test case class.

Cheers,
Zsolt

Original comment by zsolt.zs...@gmail.com on 30 May 2008 at 8:01

Attachments:

GoogleCodeExporter commented 9 years ago
I will now produce a downloadable snapshot version with newer cglib so that this
problem is solved in trunk.

Also, I nearly finished my own implementation of proxy (using bytecode 
generation
from ASM). It's hard to commit to any dates but will try to release it in two 
weeks.

Original comment by szcze...@gmail.com on 30 May 2008 at 8:09

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
fixed in trunk:
[http://hudson.ramfelt.se/job/Mockito/lastSuccessfulBuild/artifact/trunk/target/
mockito-all-snapshot.jar
mockito-all-snapshot.jar]

Started using a new version of cglib.

Original comment by szcze...@gmail.com on 30 May 2008 at 1:04

GoogleCodeExporter commented 9 years ago
It works. Thanks for your really immediate reaction!

Zsolt

Original comment by zsolt.zs...@gmail.com on 30 May 2008 at 2:50

GoogleCodeExporter commented 9 years ago
Should this work for eclipse plug-in tests, too? I still get the exception if I 
run
my tests as a plug-in test. 

E.g. when calling in a Junit plug-in test 

       Object mock = Mockito.mock(ISelectionListener.class);

then the call toMock.getSigners() returns NULL (see code below).
However, if I'm running as a JUnit test, then the same call returns the signers
information and mockito works. 

    public T createMock(Class<T> toMock, final MethodInterceptorFilter filter) {
        validateClass(toMock);
        Enhancer enhancer = createEnhancer(toMock);
        enhancer.setCallbackType(filter.getClass());

        //This is required but I could not figure out the way to test it
        //See issue #11
        if (toMock.getSigners() != null) {
            enhancer.setNamingPolicy(ALLOWS_MOCKING_CLASSES_IN_SIGNED_PACKAGES);
        }

        Class mockClass = enhancer.createClass();

        Enhancer.registerCallbacks(mockClass, new Callback[] { filter });

        Factory mock = createMock(mockClass);

        filter.setMock(mock);
        return (T) mock;
    }

Original comment by Knut.Fri...@yahoo.de on 6 Jun 2008 at 12:30

GoogleCodeExporter commented 9 years ago
Will look at it

Original comment by szcze...@gmail.com on 6 Jun 2008 at 3:16

GoogleCodeExporter commented 9 years ago
Don't know yet why it happens but I found jMock guys had similar problems. See 
here
http://jira.codehaus.org/browse/JMOCK-127 

I'm still looking at it but if you can please try Eclipse-BuddyPolicy /
Eclipse-RegisterBuddy workaround (I don't know what it is... :)

Original comment by szcze...@gmail.com on 10 Jun 2008 at 8:20

GoogleCodeExporter commented 9 years ago
I tried that already (the jmocks bugreport is also from me:-)

Typically a plug-in "sees" only its own classes and not the classes in other
plug-ins. With Eclipse-RegisterBuddy I can increase the visibility of classes 
for the
classloader of a plug-in. This works quite perfect for my own plugins but not 
for
Eclipse plugins (which are read-only). So seems that an interface in an Eclipse
plug-in is not visible for the classloader of the plug-in that has the tests in 
it
(even though I have an dependecy). 

See: http://www.eclipsezone.com/articles/eclipse-vms/

Ulli

Original comment by Knut.Fri...@yahoo.de on 10 Jun 2008 at 9:15

GoogleCodeExporter commented 9 years ago
Ok, thanks for info. The exception at the bottom is:

Caused by: java.lang.ClassNotFoundException: net.sf.cglib.proxy.Factory

I tried to play with buddies for various packages but no luck :(

Is this issue solved in JMock, then?

Original comment by szcze...@gmail.com on 12 Jun 2008 at 9:22

GoogleCodeExporter commented 9 years ago
I think this is not solved. Since JMock uses proxies for interfaces this is no 
big
problem in JMock (no cglib), so the bug was closed. Typically you need not to 
have
mocks for Eclipse classes, you only mock interfaces. 

Original comment by Knut.Fri...@yahoo.de on 12 Jun 2008 at 6:46

GoogleCodeExporter commented 9 years ago
Possible solutions: 

1. Make a special case for interfaces and use standard java mechanism for 
creating
proxies. It would solve *most* problems (most plugin-related work in eclipse 
strongly
uses interfaces).

2. Debug cglib+eclipse and find out why it doesn't work. I don't think it's 
related
to mockito - it's rather a feature of combo cglib+eclipse.

3. Write own proxy implementation with ASM. I almost finished but stopped 
working
once cglib 2.2 was released.

I prefer #2 but it will take some time. I don't think it will make it to the 1.4
which I want to release in a day or two.

Any help is much appreciated. Here are my observations about the problem:

The root exception is: java.lang.ClassNotFoundException: 
net.sf.cglib.proxy.Factory
I tried to play with buddy settings using net.sf.cglib.proxy packages but no 
luck.
The really interesting behavior is that net.sf.cglib.proxy.Factory IS loadable,
because I can do this in the test (!?):
net.sf.cglib.proxy.Factory.class.getName()

Original comment by szcze...@gmail.com on 17 Jun 2008 at 1:32

GoogleCodeExporter commented 9 years ago
Did #2

It's fixed in trunk.

Cglib takes the ClassLoader of the mocked class as default one if no ClassLoader
provided. When running tests as separate Eclipse project, the default 
ClassLoader of
mocked class was the Eclipse's one (which does not have access to classes from
plugins, obviously). Fixed by setting ClassLoader on Enhancer.

Original comment by szcze...@gmail.com on 29 Jun 2008 at 11:08

GoogleCodeExporter commented 9 years ago

Original comment by szcze...@gmail.com on 19 Apr 2009 at 7:40