mlinhard / mockito

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

Support Partial Mocking #299

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I want to mock a class that has some methods with signatures that contain types 
that are not available. These methods are not relevant for the test and they 
will not be called.

At the moment it seems that these classes can not be mocked by Mockito. A 
NoClassDefFound exception is thrown when the mock is tried to be created.

The proposed "spy" mechanism could help, however in my case an abstract class 
has to be mocked -> no instance to spy can easily be created.

Original issue reported on code.google.com by stefan.w...@gmx.de on 12 Dec 2011 at 10:18

GoogleCodeExporter commented 9 years ago
Hi,

We can't really do much about this, it is the classloading mechanism of the JVM 
that tells you it can not load this class in memory if his dependencies can not 
be found.

It will fail anyway if you try to use this class and you don't have the related 
efferent dependencies.

Original comment by brice.du...@gmail.com on 12 Dec 2011 at 10:26

GoogleCodeExporter commented 9 years ago
I guess the problem is not the ClassLoading mechanism itself but the method 
Class.getDeclaredMethods(). This method throws an exception because not all 
necessary types are available to form the result of the method call.

I guess, one would need a method 
Class.getAllDeclaredMethodsWhoseTypeSignaturesCanBeResolved(). Then these 
method could be mocked.

However, you can close this issue. The requirement seems exotic.

Original comment by stefan.w...@gmx.de on 16 Dec 2011 at 7:35

GoogleCodeExporter commented 9 years ago
Yes, it's not a classloading problem but rather the way the JVM classloading 
mechanism was designed.

When the classloader load the class, it will try to link it with other 
artifacts, during this phase the JVM will :
1. Do some verifications like the correctness the bytecode, maybe some security 
stuff too
2. prepare the class, like space allocation, default value etc.
3. perform the resolution, this where symbolic types get resolved to the actual 
one (it will actually look to the class constant pool), this phase might be 
delayed until the first use of the type (eg an instanciation or accessing the 
class using for example the ".class" literal)

So as long as you don't actively use that type you can be happy. Which is 
clearly not the case when : 
A. Create an instance
B. Introspect the type
C. Subclassing a type
D. Accessing a static member being a method or a non final field

In these case resolution has to happen and you will see an *error* thrown by 
the JVM, aka the java.lang.NoClassDefFoundError. You cannot avoid it.

Our proxing mechanism (as probably every mock framework) actually use the above 
mentionned points A, B and C. 

However what I didn't know (nor expect) is that the JVM also apply the "active 
use" principle on the types in the method signature themselves. So as long as 
you don't *actively use* a method you are fine. But it seems that if you do at 
least the following :
A. Invoke the method
B. Introspect the methods on a available type

the JVM will look for the types in these methods.

Anyway it is unfixable at all so I'll invalidate this issue.

Original comment by brice.du...@gmail.com on 16 Dec 2011 at 11:20