Skip to content

can't mock final methods with powermock-mockito2 1.7.0.RC4 and mockito2 inline feature enabled #774

@bio007

Description

@bio007

Hi, I have a problem using mockito2 feature - mocking of final methods, with powrmock 1.7.0.RC4. When I include testCompile 'org.mockito:mockito-core:2.7.5' into my build.gradle file and enable mock-maker-inline mechanism according to mockito documentation, everything works just fine.

At the moment I change the dependency to testCompile 'org.powermock:powermock-api-mockito2:1.7.0RC4' the test fails with seemingly unrelated exceptions:

org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.test.app.map.MenuViewModelTest.run_action_on_close(MenuViewModelTest.kt:49)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:

  1. missing thenReturn()
  2. you are trying to stub a final method, which is not supported
    3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

at com.test.app.map.MenuViewModelTest.run_action_on_close(MenuViewModelTest.kt:50)
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.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
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:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
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.AppMain.main(AppMain.java:147)

or

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Runnable$$EnhancerByMockitoWithCGLIB$$b48288eb cannot be returned by doAction()
doAction() should return int
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:

  1. This exception might occur in wrongly written multi-threaded tests.
    Please refer to Mockito FAQ on limitations of concurrency testing.
  2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
    - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.

The test is in kotlin but it's the same in java, I have tried.

 @Test
 fun run_action_on_close() {
    val runnable = mock<Runnable>(Runnable::class.java)    //mock Runnable.class

    doReturn(runnable).`when`(mMenuItem)!!.getAction(mContext)
    mViewModel!!.onItemClick(mMenuItem)

    verify<Runnable>(runnable).run()
}

The real problem is definitely in final method getAction(Context context). When this method is not final everything works again. But as I mentioned this exact test works with mockito-core:2.7.5 dependency. With powermock-api-mockito2:1.7.0RC4 (which depends on exact same mockito-core:2.7.5 version) the test fails.

I'm running this on Windows 10 x64.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions