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

Bug: MockK is not runnable together with PowerMockito #79

Open
RafaRuiz opened this Issue May 31, 2018 · 17 comments

Comments

5 participants
@RafaRuiz
Copy link

RafaRuiz commented May 31, 2018

Prerequisites

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed

Expected Behavior

Mocking a static method

Failure Information (for bugs)

java.lang.ExceptionInInitializerError
at my.package.ConfigUseCaseTests.getConfigs_fromJson(ConfigUseCaseTests.kt:33)
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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
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.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:47)
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: io.mockk.MockKException: Failed to load plugin io.mockk.proxy.jvm.JvmMockKAgentFactory
at io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:152)
at io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:138)
... 29 more
Caused by: java.lang.IllegalStateException: Error during attachment using: net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@1c72da34
at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:377)
at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:351)
at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:319)
at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:305)
at io.mockk.proxy.jvm.MockKInstrumentation.(MockKInstrumentation.java:57)
at io.mockk.proxy.jvm.JvmMockKAgentFactory.(JvmMockKAgentFactory.java:11)
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 io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:150)
... 30 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:77)
at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:372)
... 41 more
Caused by: java.lang.NullPointerException
at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:187)
... 47 more

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

  • MockK version: 1.8.0
  • OS: Mac OS High Sierra
  • Kotlin version: 1.2.30
  • JDK version: 1.8.0_161
  • Type of test: unit test

Minimal reproducible code (the gist of this issue)

// These are some of the Gradle implementations.
    // Power Mockito
    testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
    testImplementation 'org.powermock:powermock-module-junit4-rule-agent:1.6.1'
    testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
    testImplementation 'org.powermock:powermock-module-junit4:1.6.1'

    // Mockk
    testImplementation "io.mockk:mockk:1.8"

    // Mockito
    def mockitoVersion = "1.5.0"
    testImplementation "org.mockito:mockito-core:$mockitoVersion"
    testImplementation "com.nhaarman:mockito-kotlin-kt1.1:$mockitoVersion"
    androidTestImplementation("com.nhaarman:mockito-kotlin-kt1.1:$mockitoVersion", {
        exclude group: 'org.mockito', module: 'mockito-core'
    })
    androidTestImplementation 'org.mockito:mockito-android:2.11.0'

    class ConfigUseCaseTests : UnitTestsResource() {
    
        private lateinit var configUseCase: ConfigUseCase
    
        @Before
        override fun setUp() {
            super.setUp()
            configUseCase = ConfigUseCase()
        }
    
        @Test
        fun getConfigs_fromJson() {
            objectMockk(SharedPreferencesHelper).mock()
            every { SharedPreferencesHelper.loadString(isA(), isA(), isA(), isA()) } returns "wooo"
            System.out.println("String:${SharedPreferencesHelper.loadString(context, "", "", null)}")
        }
    }

I've also tested it with staticMockk or any other examples provided but I'm getting the same error.

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

Looks like the agent is not attachable.

I know this is for windows, but try to put attach.so (I don't know how indeed it's called for macosx) in jdk/jre/lib to a PATH.

https://stackoverflow.com/questions/39420830/virtualmachine-attach-failing

(read show more comments)

@RafaRuiz

This comment has been minimized.

Copy link
Author

RafaRuiz commented May 31, 2018

I've just realised that removing PowerMockito doesn't throw that.

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

Oh, ok just was writting to try that.

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

So it's powermock issue, because I was fixing integration with mockito already.

@RafaRuiz

This comment has been minimized.

Copy link
Author

RafaRuiz commented May 31, 2018

Sorry to do another comment.
I'm using Mac OS not Windows in this case.

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

Yeah I know, but attach.so should be in Linux and Mac OS X

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

Anyway I'd like to reproduce and fix it if possible. Thanks for reporting

@RafaRuiz

This comment has been minimized.

Copy link
Author

RafaRuiz commented May 31, 2018

Sure, what else would you need?

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented May 31, 2018

I think I have enough information for now

@oleksiyp oleksiyp changed the title Can't integrate Mockk 1.7.0 Bug: MockK is not runnable together with PowerMockito May 31, 2018

@oleksiyp oleksiyp added the bug label May 31, 2018

@misrakli

This comment has been minimized.

Copy link

misrakli commented Oct 16, 2018

Hi,
thank You for the great work, we're using mockk successful in our projects.
But we faced the same problem with powermock. Any update for this issue in sight?

MockK : 1.8.3
PowerMock: 2.0.0-beta.5
Kotlin: 1.2.31

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented Oct 16, 2018

Hi, no progress so far. If will have some spare time will check that

@karolzdebel

This comment has been minimized.

Copy link

karolzdebel commented Oct 24, 2018

We began integrating Mockk into our Android SDK over at Flybits however this issue is holding us back since many existing unit tests require PowerMock stubbing functionality.

@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented Oct 25, 2018

@karolzdebel
Can you provide build.gradle and minimal classes to reproduce it?
Because right now I am not able to reproduce it. Bumping at error although doing it from the documentation example:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
@karolzdebel

This comment has been minimized.

Copy link

karolzdebel commented Oct 25, 2018

@oleksiyp

Running the JavaClassTest below with the given gradle throws:

java.lang.NoClassDefFoundError: io/mockk/proxy/jvm/dispatcher/JvmMockKWeakMap

Gradle:

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
testImplementation "io.mockk:mockk:1.8.9"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

Test class:

package com.example.karol.showcrashapp

import io.mockk.MockKAnnotations
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.modules.junit4.PowerMockRunner

@RunWith(PowerMockRunner::class)
class SomeJavaClassTest {

    @Before
    fun setup(){
        MockKAnnotations.init(this)

    }

    @Test
    fun someTest(){

    }
}
@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented Nov 11, 2018

At least I found some workaround. Provided example do not throw any exception. Do not know if it will work in general.

@RunWith(PowerMockRunner::class)
@PowerMockIgnore(
    "io.mockk.proxy.jvm.dispatcher.JvmMockKWeakMap",
    "io.mockk.proxy.jvm.dispatcher.JvmMockKDispatcher"
)
class SomeJavaClassTest {

    @Before
    fun setup(){
        MockKAnnotations.init(this)

    }

    @Test
    fun someTest(){

    }
}
@oleksiyp

This comment has been minimized.

Copy link
Collaborator

oleksiyp commented Nov 11, 2018

I played a bit more. Following code is printing for me null for some reason.

@RunWith(PowerMockRunner::class)
@PowerMockIgnore(
    "io.mockk.proxy.jvm.dispatcher.JvmMockKWeakMap",
    "io.mockk.proxy.jvm.dispatcher.JvmMockKDispatcher"
)
class SomeJavaClassTest {
    open class Tst(val x: Int = 5) {
        open fun tst() = "abc$x"
    }

    @Test
    fun testPowerMock(){
        val tst = Tst(6)
        PowerMockito.whenNew(Tst::class.java)
            .withAnyArguments()
            .thenReturn(tst)
        println(Tst())
    }
}

There is no MockK involved here at all and thus it should not load. Somebody should check if these workarounds are really working. If yes I can submit PR to PowerMock to include this as a permanent solution.

The general conclusion is that MockK lacks integration tests with other frameworks.

@pentiumao

This comment has been minimized.

Copy link

pentiumao commented Nov 15, 2018

I played a bit more. Following code is printing for me null for some reason.

@RunWith(PowerMockRunner::class)
@PowerMockIgnore(
    "io.mockk.proxy.jvm.dispatcher.JvmMockKWeakMap",
    "io.mockk.proxy.jvm.dispatcher.JvmMockKDispatcher"
)
class SomeJavaClassTest {
    open class Tst(val x: Int = 5) {
        open fun tst() = "abc$x"
    }

    @Test
    fun testPowerMock(){
        val tst = Tst(6)
        PowerMockito.whenNew(Tst::class.java)
            .withAnyArguments()
            .thenReturn(tst)
        println(Tst())
    }
}

There is no MockK involved here at all and thus it should not load. Somebody should check if these workarounds are really working. If yes I can submit PR to PowerMock to include this as a permanent solution.

The general conclusion is that MockK lacks integration tests with other frameworks.

@oleksiyp Not worked for my project until I changed the code as below :

@PowerMockIgnore(
    "io.mockk.proxy.*"
)

This is like the case that Robolectric will encounter also.
Robolectric : Using-PowerMock

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.