cloud1105 / mockito

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

Container.add(mock(Container.class)) fails in Java 7 #416

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The following code fails with a NullPointerExeption in 
Container.updateGraphicsData when run with Java 7. 

    Container container = mock(Container.class);
    JPanel panel = new JPanel();
    panel.add(container);

The package-protected method updateGraphicsData of container is executed 
although it should be mocked. Running the same code with Java 6 succeeds.

Tested with Mockito 1.9.5.

Steps to reproduce the problem:

* Unpack the attached test case.
* Set JAVA_HOME to a Java 7 JDK.
* Run mvn install in test case directory.

The test fails with a NullPointerException.

When JAVA_HOME is set to a Java 6 JDK, the test case succeeds.

Surprisingly, while from the NullPointerException stack trace it seems that 
panel.updateGraphicsData fails, in the Eclipse debugger you can see that it is 
actually the mocked container where the exception occurs (see attached 
screenshot).

This problem is also described in 
http://code.google.com/p/mockito/issues/detail?id=127#c12 . I've created a new 
issue because the other issue is about OSGi and this one is about Java 7 
compatibility, which might affect more Mockito users.

Original issue reported on code.google.com by tensb...@gmail.com on 29 Jan 2013 at 10:34

GoogleCodeExporter commented 8 years ago

Original comment by tensb...@gmail.com on 29 Jan 2013 at 10:37

Attachments:

GoogleCodeExporter commented 8 years ago
Mmmh looks interesting, could you reproduce it with your own classes ?

Just as a reminder, it's usually a bad idea to mock types you don't own.

Original comment by brice.du...@gmail.com on 29 Jan 2013 at 10:46

GoogleCodeExporter commented 8 years ago
Thanks for the fast feedback. I experimented some more and now think that this 
is not a Mockito bug but one of the normal limitations of cglib.

The implementation of java.awt.Container.addImpl has changed between Java 6 and 
7. The package-private methods which fail with Java 7 did not exists in Java 6. 
So this explains why the test case works with Java 6.

The other question is why the package-private methods are not stubbed by cglib. 
I guess this is because Container is loaded from the bootstrap class loader and 
cglib thus can't override the package-private classes. 

I think you can close this issue as "not a bug" and also change the summary to 
"Container.add(mock(Container.class)) fails in Java 7". My experiments 
convinced me that mocking package-protected methods generally work the same in 
both Java 6 and 7.

Original comment by tensb...@gmail.com on 29 Jan 2013 at 3:07

GoogleCodeExporter commented 8 years ago
Glad you came around it.

> The implementation of java.awt.Container.addImpl has changed between Java 6 
and 7.

That's one of the reason why mocking type we don't own is a bad idea ! Instead 
using integration tests is probably more relevant. You should read the Growing 
Object Oriented Software book, it can be enlightening for in some way. The 
authors are at the origin of many testing framework Hamcrest, jMock, 
windowlicker (for swing, ...) and influenced many others.

> The other question is why the package-private methods are not stubbed by 
cglib. I guess this is because Container is loaded from the bootstrap class 
loader and cglib thus can't override the package-private classes. 

Yes I believe you are right, I run a few tests and there is a '$' before the 
package of system classes, which means package-private methods of these system 
class are not visible in the different package of the proxy. Actually package 
protected methods are even enforced by the compiler or the JVM itself.

I think the the reason behind this '$' is related to the security of the JVM 
itself, i.e. we (coders, or proxies) don't have the permission to define 
classes in those packages (even in different jars), so CGLIB chose to prefix 
the generated classname by this '$'.

Anyway thank you for reporting, it's actually a very valuable report, which 
helped me re/discover a few thing on security, permission, CGLIB, package 
methods. Also it shows another example why mocking types not owned can blow at 
you in expected ways.

Cheers,
Brice

Original comment by brice.du...@gmail.com on 29 Jan 2013 at 3:59

GoogleCodeExporter commented 8 years ago
Thank your for your feedback. The book looks interesting, I'll have a look at 
it.

Cheers
Michael

Original comment by tensb...@gmail.com on 30 Jan 2013 at 7:40

GoogleCodeExporter commented 8 years ago
:)

Also a small erratum : 
Also it shows another example why mocking types not owned can blow at you in 
UNexpected ways.

Original comment by brice.du...@gmail.com on 30 Jan 2013 at 9:46