Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mockito mock-maker-inline does not work with Robolectric #811

Open
manuelvicnt opened this issue Jun 16, 2017 · 5 comments
Open

Mockito mock-maker-inline does not work with Robolectric #811

manuelvicnt opened this issue Jun 16, 2017 · 5 comments

Comments

@manuelvicnt
Copy link

manuelvicnt commented Jun 16, 2017

PowerMock is supposed to solve the integration problem with Mockito mock-maker-inline. However, since it uses its custom PowerMockMaker, it cannot initialize Byte Buddy mock maker.

The problem is this one: "This mock maker is not supported on Android" when running side by side with Robolectric. It seems like Robolectric already solved this issue here: robolectric/robolectric#2761

Caused by: org.mockito.exceptions.base.MockitoInitializationException: 
Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)

Libraries used:
mockitoVersion -> 2.8.9
powermockVersion -> 1.7.0
robolectricVersion -> 3.4-rc2

When you try to mock a simple final class with the JUnit4 or PowerMock runners you can see this error:

java.lang.RuntimeException: Invoking the beforeTestMethod method on PowerMock test listener org.powermock.api.extension.listener.AnnotationEnabler@4229bb3f failed.

	at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:84)
	at org.powermock.modules.junit4.internal.impl.NotificationBuilder$OngoingTestRun.<init>(NotificationBuilder.java:90)
	at org.powermock.modules.junit4.internal.impl.NotificationBuilder.testStartHasBeenFired(NotificationBuilder.java:233)
	at org.powermock.modules.junit4.internal.impl.PowerMockRunNotifier.fireTestStarted(PowerMockRunNotifier.java:112)
	at org.junit.internal.runners.model.EachTestNotifier.fireTestStarted(EachTestNotifier.java:42)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:323)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:149)
	at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:141)
	at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:132)
	at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:141)
	at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
	at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
	at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker
	at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:66)
	at com.sun.proxy.$Proxy14.createMock(Unknown Source)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:116)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:69)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
	at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:192)
	at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:107)
	at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:55)
	at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:82)
	... 30 more
Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@73ee04c8
	at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:101)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:45)
	at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:18)
	at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:17)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.getMockMaker(DefaultMockCreator.java:140)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:99)
	... 36 more
Caused by: java.lang.IllegalStateException: Failed to load MockMaker implementation: org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
	at org.powermock.api.mockito.mockmaker.MockMakerLoader.load(MockMakerLoader.java:39)
	at org.powermock.api.mockito.mockmaker.PowerMockMaker.<init>(PowerMockMaker.java:45)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:96)
	... 41 more
Caused by: org.mockito.exceptions.base.MockitoInitializationException: 
Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)

Java               : 1.8
JVM vendor name    : JetBrains s.r.o
JVM vendor version : 25.112-b736
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 1.8.0_112-release-b736
JVM info           : mixed mode
OS name            : Mac OS X
OS version         : 10.12.5

	at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.<init>(InlineByteBuddyMockMaker.java:172)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.powermock.api.mockito.mockmaker.MockMakerLoader.load(MockMakerLoader.java:36)
	... 48 more
Caused by: java.lang.IllegalStateException: Error during attachment using: net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@55607a32
	at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:379)
	at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:353)
	at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:321)
	at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:307)
	at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.<clinit>(InlineByteBuddyMockMaker.java:102)
	... 54 more
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at net.bytebuddy.agent.Attacher.install(Attacher.java:78)
	at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:374)
	... 58 more
Caused by: java.lang.NullPointerException
	at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:182)
	... 64 more
@thekingn0thing
Copy link
Member

@xian and @raphw could you help me to clarify the issue and current state with robolectric/robolectric#2761

PowerMock uses the following code to load InlineByteBuddyMockMaker.

        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            loader = ClassLoader.getSystemClassLoader();
        }
        
        String mockMakerClassName = mockitoConfiguration.getMockMakerClass();
        
        try {
            Class<?> mockMakerClass = loader.loadClass(mockMakerClassName);
            Object mockMaker = mockMakerClass.newInstance();
            return MockMaker.class.cast(mockMaker);
        } catch (Exception e) {
            throw new IllegalStateException("Failed to load MockMaker implementation: " + mockMakerClassName, e);
        }

I guess that in this case Robolectric ClassLoader is used and everything should be fine.

I'm not sure, but maybe correct way to load a class will be
Class.forName(mockMakerClassName).newInstance()

@raphw
Copy link

raphw commented Jun 19, 2017

The inline Mock maker needs to load a class explicitly as it must inject a type into the bootstrap class loader. I guess some explicit class loading is triggering some code before the inline mock maker is loaded such that this yields a race?

I am however confused over this mistake:

Caused by: java.lang.NullPointerException
at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:182)

Could you look at the line in question and debug what is missing? Are you running on a JDK?

@thekingn0thing
Copy link
Member

@raphw,

As I see in stacktrace it was OpenJDK

Java : 1.8
JVM vendor name : JetBrains s.r.o
JVM vendor version : 25.112-b736
JVM name : OpenJDK 64-Bit Server VM
JVM version : 1.8.0_112-release-b73

@manuelvicnt
Copy link
Author

@raphw @thekingnothing Yes, it's OpenJDK because I'm using Robolectric

@kassim
Copy link

kassim commented Dec 4, 2020

did you ever solve this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants