Repository: mockito/mockito
Issue: ClassLoader built by mockito is not able to load declared types in the hierarchy in OSGi

We develop in OSGi environment and we are using latest version of mockito available on maven central 2.23.4

We got an issue when we mock classes given to guice (sisu) for injection. Sisu/Guice analyse all declared fields and methods for the input type and its super classes to built a sort of index of known types. In OSGi it fails with ClassNotFoundException on mocked classes. The reason is that the mocked class built with `SubclassBytecodeGenerator` has a classloader not able to load types reachable only by supertypes. In OSGi this does not happen because each class has associated the classloader from which is loaded. This guarantee that the class is able to reach/load each type it declares (by its methods, fields or annotations).

Example:

- Bundle A
`foo.Class1` has a protected method that returns foo.impl.OtherClass
`foo.impl.OtherClass`

- Bundle B (imports only `foo` package from bundle A)
`acme.Class2 extends Class1`

`Mockito.mock(foo.Class1).getDeclaredMethods()` will fails. To fix this issue `SubclassBytecodeGenerator` should compose a classloader (`MultipleParentClassLoader`) with also the classloader of superclass the mocked type (`features.mockedType`).

Issue comments:
@raphw FYI

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java
index 1985e80863..75b13fcfd9 100644
--- a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java
+++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java
@@ -28,7 +28,9 @@
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Random;
 
 import static java.lang.Thread.currentThread;
@@ -79,7 +81,7 @@ protected SubclassBytecodeGenerator(SubclassLoader loader, Implementation readRe
     @Override
     public <T> Class<? extends T> mockClass(MockFeatures<T> features) {
         ClassLoader classLoader = new MultipleParentClassLoader.Builder()
-            .appendMostSpecific(features.mockedType)
+            .appendMostSpecific(getAllTypes(features.mockedType))
             .appendMostSpecific(features.interfaces)
             .appendMostSpecific(currentThread().getContextClassLoader())
             .appendMostSpecific(MockAccess.class)
@@ -173,6 +175,17 @@ public <T> Class<? extends T> mockClass(MockFeatures<T> features) {
             .getLoaded();
     }
 
+    private <T> Collection<Class<? super T>> getAllTypes(Class<T> type) {
+        Collection<Class<? super T>> supertypes = new LinkedList<Class<? super T>>();
+        supertypes.add(type);
+        Class<? super T> superType = type;
+        while (superType != null) {
+            supertypes.add(superType);
+            superType = superType.getSuperclass();
+        }
+        return supertypes;
+    }
+
     private static ElementMatcher<MethodDescription> isGroovyMethod() {
         return isDeclaredBy(named("groovy.lang.GroovyObjectSupport"));
     }


Test patch: