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 70abf95fb9..3dadd3fa46 100644 --- a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java +++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; @@ -97,10 +98,31 @@ private static boolean needsSamePackageClassLoader(MockFeatures features) { // package private methods. return true; } + if (hasNonPublicTypeReference(features.mockedType)) { + return true; + } + for (Class iface : features.interfaces) { if (!Modifier.isPublic(iface.getModifiers())) { return true; } + if (hasNonPublicTypeReference(iface)) { + return true; + } + } + return false; + } + + private static boolean hasNonPublicTypeReference(Class iface) { + for (Method method : iface.getMethods()) { + if (!Modifier.isPublic(method.getReturnType().getModifiers())) { + return true; + } + for (Class param : method.getParameterTypes()) { + if (!Modifier.isPublic(param.getModifiers())) { + return true; + } + } } return false; } diff --git a/src/test/java/org/mockitousage/bugs/creation/PackagePrivateWithContextClassLoaderTest.java b/src/test/java/org/mockitousage/bugs/creation/PackagePrivateWithContextClassLoaderTest.java index 4f6ffbee19..95095f32f4 100644 --- a/src/test/java/org/mockitousage/bugs/creation/PackagePrivateWithContextClassLoaderTest.java +++ b/src/test/java/org/mockitousage/bugs/creation/PackagePrivateWithContextClassLoaderTest.java @@ -31,10 +31,24 @@ int packagePrivateMethod() { abstract void packagePrivateAbstractMethod(); } + public interface PublicInterfaceWithPackagePrivateMethodParam { + void doSomething(PackagePrivateInterface i); + } + + public interface PublicInterfaceWithPackagePrivateMethodReturn { + PackagePrivateInterface doSomething(); + } + + public interface PublicInterfaceOverridesPackagePrivateMethodReturn { + PublicChildOfPackagePrivate doSomething(); + } + public interface PublicInterface {} interface PackagePrivateInterface {} + public interface PublicChildOfPackagePrivate extends PackagePrivateInterface {} + static class PackagePrivateClass {} @Before @@ -55,6 +69,28 @@ public void should_be_able_to_mock_package_private_method() throws Exception { assertThat(publicClass.packagePrivateMethod()).isEqualTo(3); } + @Test + public void should_be_able_to_mock_interface_method_package_private_param() throws Exception { + PublicInterfaceWithPackagePrivateMethodParam publicClass = + mock(PublicInterfaceWithPackagePrivateMethodParam.class); + publicClass.doSomething(null); + } + + @Test + public void should_be_able_to_mock_interface_method_package_private_return() throws Exception { + PublicInterfaceWithPackagePrivateMethodReturn publicClass = + mock(PublicInterfaceWithPackagePrivateMethodReturn.class); + PackagePrivateInterface packagePrivateInterface = publicClass.doSomething(); + } + + @Test + public void should_be_able_to_mock_interface_method_package_private_return_override() + throws Exception { + PublicInterfaceOverridesPackagePrivateMethodReturn publicClass = + mock(PublicInterfaceOverridesPackagePrivateMethodReturn.class); + PackagePrivateInterface packagePrivateInterface = publicClass.doSomething(); + } + @Test public void should_be_able_to_mock_package_private_class() throws Exception { PackagePrivateClass mock = mock(PackagePrivateClass.class);