From 2838de8e59c4b81d1773848fc5417267feb98e65 Mon Sep 17 00:00:00 2001 From: Po-Dar Wang Date: Fri, 24 Mar 2017 00:53:12 -0700 Subject: [PATCH] Issue #769: PowerMockMaker with Mockito2. --- .../powermock-api-mockito2/build.gradle | 3 ++ .../internal/mockmaker/PowerMockMaker.java | 36 ++++++++++++- .../pluginswitch/PowerMockPluginSwitch.java | 23 +++++++++ .../PowerMockPluginSwitchTest.java | 50 +++++++++++++++++++ .../org.mockito.plugins.PluginSwitch | 1 + .../ClassWithNonPublicParent.java | 9 ++++ 6 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 powermock-api/powermock-api-mockito2/build.gradle create mode 100644 powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitch.java create mode 100644 powermock-api/powermock-api-mockito2/src/test/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitchTest.java create mode 100644 powermock-api/powermock-api-mockito2/src/test/resources/mockito-extensions/org.mockito.plugins.PluginSwitch create mode 100644 tests/utils/src/main/java/samples/classwithnonpublicparent/ClassWithNonPublicParent.java diff --git a/powermock-api/powermock-api-mockito2/build.gradle b/powermock-api/powermock-api-mockito2/build.gradle new file mode 100644 index 000000000..4eeab6851 --- /dev/null +++ b/powermock-api/powermock-api-mockito2/build.gradle @@ -0,0 +1,3 @@ +dependencies { + testCompile(project(":tests:utils")) +} \ No newline at end of file diff --git a/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java b/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java index 824fe8d1b..3e3c9513e 100644 --- a/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java +++ b/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java @@ -18,6 +18,7 @@ import org.mockito.internal.InternalMockHandler; import org.mockito.internal.creation.MockSettingsImpl; +import org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker; import org.mockito.internal.stubbing.InvocationContainer; import org.mockito.internal.util.MockNameImpl; import org.mockito.invocation.Invocation; @@ -25,6 +26,7 @@ import org.mockito.mock.MockCreationSettings; import org.mockito.plugins.MockMaker; import org.mockito.stubbing.Answer; +import org.powermock.api.mockito.internal.pluginswitch.PowerMockPluginSwitch; import org.powermock.api.mockito.repackaged.CglibMockMaker; import org.powermock.core.classloader.MockClassLoader; @@ -40,10 +42,16 @@ * For more details see the {@link org.powermock.api.mockito.internal.invocation.ToStringGenerator}. */ public class PowerMockMaker implements MockMaker { + + private static boolean isEnabled = true; private final MockMaker cglibMockMaker = new CglibMockMaker(); + private final MockMaker byteBuddyMockMaker = new ByteBuddyMockMaker(); @Override public T createMock(MockCreationSettings settings, MockHandler handler) { + if(!isEnabled) { + return byteBuddyMockMaker.createMock(settings, handler); + } T mock = cglibMockMaker.createMock(settings, handler); ClassLoader classLoader = cglibMockMaker.getClass().getClassLoader(); if (classLoader instanceof MockClassLoader) { @@ -56,8 +64,9 @@ public T createMock(MockCreationSettings settings, MockHandler handler) { @Override public MockHandler getHandler(Object mock) { - // Return a fake mock handler for static method mocks - if (mock instanceof Class) { + if(!isEnabled) { + return byteBuddyMockMaker.getHandler(mock); + } else if (mock instanceof Class) { // Return a fake mock handler for static method mocks return new PowerMockInternalMockHandler((Class) mock); } else { return cglibMockMaker.getHandler(mock); @@ -66,11 +75,18 @@ public MockHandler getHandler(Object mock) { @Override public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) { + if(!isEnabled) { + byteBuddyMockMaker.resetMock(mock, newHandler, settings); + return; + } cglibMockMaker.resetMock(mock, newHandler, settings); } @Override public TypeMockability isTypeMockable(Class type) { + if (!isEnabled) { + byteBuddyMockMaker.isTypeMockable(type); + } return cglibMockMaker.isTypeMockable(type); } @@ -106,4 +122,20 @@ public Object handle(Invocation invocation) throws Throwable { return null; } } + + /** + * @deprecated Please use {@link PowerMockPluginSwitch#disablePowerMockMaker} instead + */ + @Deprecated + public static void disablePowerMockMaker() { + isEnabled = false; + } + + /** + * @deprecated Please use {@link PowerMockPluginSwitch#enablePowerMockMaker} instead + */ + @Deprecated + public static void enablePowerMockMaker() { + isEnabled = true; + } } diff --git a/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitch.java b/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitch.java new file mode 100644 index 000000000..5ee549e43 --- /dev/null +++ b/powermock-api/powermock-api-mockito2/src/main/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitch.java @@ -0,0 +1,23 @@ +package org.powermock.api.mockito.internal.pluginswitch; + +import org.mockito.Mockito; +import org.mockito.plugins.PluginSwitch; +import org.powermock.api.mockito.internal.mockmaker.PowerMockMaker; + +public class PowerMockPluginSwitch implements PluginSwitch { + + @Override + public boolean isEnabled(String pluginClassName) { + return true; + } + + public static void disablePowerMockMaker() { + PowerMockMaker.disablePowerMockMaker(); + Mockito.reset(); + } + + public static void enablePowerMockMaker() { + PowerMockMaker.enablePowerMockMaker(); + Mockito.reset(); + } +} diff --git a/powermock-api/powermock-api-mockito2/src/test/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitchTest.java b/powermock-api/powermock-api-mockito2/src/test/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitchTest.java new file mode 100644 index 000000000..b4d40c583 --- /dev/null +++ b/powermock-api/powermock-api-mockito2/src/test/java/org/powermock/api/mockito/internal/pluginswitch/PowerMockPluginSwitchTest.java @@ -0,0 +1,50 @@ +package org.powermock.api.mockito.internal.pluginswitch; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.exceptions.misusing.MissingMethodInvocationException; +import samples.classwithnonpublicparent.ClassWithNonPublicParent; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PowerMockPluginSwitchTest { + + private String mSomeOtherString = "some other string"; + + @After + @Before + public void setup() { + PowerMockPluginSwitch.enablePowerMockMaker(); + } + + @Test(expected=MissingMethodInvocationException.class) + public void test_PowerMockMakerEnabled_Throws() { + PowerMockPluginSwitch.enablePowerMockMaker(); + ClassWithNonPublicParent mockClassWithNonPublicParent = mock(ClassWithNonPublicParent.class); + when(mockClassWithNonPublicParent.getSomeStringFromPackageProtectedClass()).thenReturn(mSomeOtherString); + PowerMockPluginSwitch.disablePowerMockMaker(); + } + + @Test + public void test_PowerMockMakerDisabled_MocksMethod() { + PowerMockPluginSwitch.disablePowerMockMaker(); + ClassWithNonPublicParent mockClassWithNonPublicParent = mock(ClassWithNonPublicParent.class); + when(mockClassWithNonPublicParent.getSomeStringFromPackageProtectedClass()).thenReturn(mSomeOtherString); + Assert.assertEquals(mSomeOtherString, mockClassWithNonPublicParent.getSomeStringFromPackageProtectedClass()); + } + + @Test + public void test_PowerMockMaker_SwitchesCorrectly() { + test_PowerMockMakerDisabled_MocksMethod(); + try { + test_PowerMockMakerEnabled_Throws(); + } catch (MissingMethodInvocationException e) { + return; + } + assertTrue("Expected exception not thrown.", false); + } +} \ No newline at end of file diff --git a/powermock-api/powermock-api-mockito2/src/test/resources/mockito-extensions/org.mockito.plugins.PluginSwitch b/powermock-api/powermock-api-mockito2/src/test/resources/mockito-extensions/org.mockito.plugins.PluginSwitch new file mode 100644 index 000000000..3e63ba478 --- /dev/null +++ b/powermock-api/powermock-api-mockito2/src/test/resources/mockito-extensions/org.mockito.plugins.PluginSwitch @@ -0,0 +1 @@ +org.powermock.api.mockito.internal.pluginswitch.PowerMockPluginSwitch \ No newline at end of file diff --git a/tests/utils/src/main/java/samples/classwithnonpublicparent/ClassWithNonPublicParent.java b/tests/utils/src/main/java/samples/classwithnonpublicparent/ClassWithNonPublicParent.java new file mode 100644 index 000000000..4586592a9 --- /dev/null +++ b/tests/utils/src/main/java/samples/classwithnonpublicparent/ClassWithNonPublicParent.java @@ -0,0 +1,9 @@ +package samples.classwithnonpublicparent; + +public class ClassWithNonPublicParent extends PackageProtectedClass {} + +class PackageProtectedClass { + public String getSomeStringFromPackageProtectedClass() { + return "some string"; + } +}