From e41a074b8e98883b19ac788eacc9c549fe72509a Mon Sep 17 00:00:00 2001 From: Charles Munger Date: Tue, 8 Jun 2021 12:01:45 -0700 Subject: [PATCH 1/2] Check package-privacy of method params --- .../bytebuddy/SubclassBytecodeGenerator.java | 22 ++++++++++++ ...kagePrivateWithContextClassLoaderTest.java | 36 +++++++++++++++++++ 2 files changed, 58 insertions(+) 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..9eb0c3b28a 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 (hasPackagePrivateParam(features.mockedType)) { + return true; + } + for (Class iface : features.interfaces) { if (!Modifier.isPublic(iface.getModifiers())) { return true; } + if (hasPackagePrivateParam(iface)) { + return true; + } + } + return false; + } + + private static boolean hasPackagePrivateParam(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); From e24e560effe894bd84d25d9af79ebcd1da8aa389 Mon Sep 17 00:00:00 2001 From: Charles Munger Date: Tue, 8 Jun 2021 13:10:45 -0700 Subject: [PATCH 2/2] Rename helper method --- .../creation/bytebuddy/SubclassBytecodeGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 9eb0c3b28a..3dadd3fa46 100644 --- a/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java +++ b/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java @@ -98,7 +98,7 @@ private static boolean needsSamePackageClassLoader(MockFeatures features) { // package private methods. return true; } - if (hasPackagePrivateParam(features.mockedType)) { + if (hasNonPublicTypeReference(features.mockedType)) { return true; } @@ -106,14 +106,14 @@ private static boolean needsSamePackageClassLoader(MockFeatures features) { if (!Modifier.isPublic(iface.getModifiers())) { return true; } - if (hasPackagePrivateParam(iface)) { + if (hasNonPublicTypeReference(iface)) { return true; } } return false; } - private static boolean hasPackagePrivateParam(Class iface) { + private static boolean hasNonPublicTypeReference(Class iface) { for (Method method : iface.getMethods()) { if (!Modifier.isPublic(method.getReturnType().getModifiers())) { return true;