PowerMockito.spy(StaticClass) still causes real method invocation

5,865 views
Skip to first unread message

matthias

unread,
Jul 5, 2010, 11:28:34 AM7/5/10
to PowerMock
Hi,

I am currently playing with PowerMock + Mockito as a solution to
partial stubbing and static method stubbing fo our Android app (no
instrumentation tests, I know that doesn't work, just normal JUnit
tests executed on a Sun JVM), and it seems to work fine (tests pass)
except that PowerMock still prints an error (NullpointerException) to
standard out when running the tests. Apparently, although in the
actual test the method is correctly stubbed, it invokes the original
version internally in
org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl
$1.invoke and a NPE is thrown because it tries to access the mocked
argument (the methods of which will all return NULL).

Here is the test code (it's gonna be an Android test):

@RunWith(PowerMockRunner.class)
@PrepareForTest(Util.class)
public class PowerMockitoTest {

@Test
public void testWithPowerMock() {
PowerMockito.spy(Util.class);


when(Util.getApplicationVersion(isA(Context.class))).thenReturn("spied!");

Context ctx = mock(Context.class);
assertEquals("spied!", Util.getApplicationVersion(ctx));
}
}

the test passes, but prints the following error stack trace:

java.lang.NullPointerException
at com.qype.radar.support.Util.getApplicationVersion(Util.java:286)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl
$1.invoke(MockitoMethodInvocationControl.java:220)
at
org.mockito.internal.invocation.realmethod.FilteredCGLIBProxyRealMethod.invoke(FilteredCGLIBProxyRealMethod.java:
27)
at
org.mockito.internal.invocation.Invocation.callRealMethod(Invocation.java:
210)
at
org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:
36)
at org.mockito.internal.MockHandler.handle(MockHandler.java:94)
at
org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:
259)
at
org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:
165)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:104)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:59)
at com.qype.radar.support.Util.getApplicationVersion(Util.java)
at
com.qype.radar.test.PowerMockitoTest.testWithPowerMock(PowerMockitoTest.java:
26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:
322)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:
86)
at
org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:
94)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:
309)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl
$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:
112)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl
$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:
73)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:
297)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:
84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:
222)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:
161)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl
$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
at
org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:
34)
at
org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:
44)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:
133)
at
org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:
112)
at
org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:
55)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:
46)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:
38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:
197)

the NPE happens because the original, unstubbed
getApplicationVersion() method accesses the Context in that line,
which returns NULL for every method since it's a mock. In other words,
at some point in the test it is still invoking the original
implementation of the stubbed method...

Very odd, I don't understand why this is happening. Also, if
PowerMock / Mockito must do this for internal purposes, is there a way
to get rid of the error message? It makes the test output unreadable.

Thanks,
Matthias

Johan Haleby

unread,
Jul 7, 2010, 4:34:21 PM7/7/10
to powe...@googlegroups.com
Hi,

When using spy for partial mocking you cannot use standard "when". This is the same with standard Mockito and PowerMock thus should behave the same way. I think you must do something like this:

doReturn("speid!").when(Util.getApplicationVersion(isA(Context.class)));

If not the "getApplicationVersion" method is invoked.

/Johan



--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.


Rajan Parmar

unread,
Nov 5, 2018, 11:49:06 PM11/5/18
to PowerMock
Thanks for the suggestion Johan. I tried doing that but it does work.

      spy(Util.class);
      doCallRealMethod().when(Util.method(any()));
 
This does not work. I get below error for that:

     org.mockito.exceptions.misusing.UnfinishedStubbingException: 
     Unfinished stubbing detected here:
     -> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36)
     
     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, you naughty developer!
      3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

Rajan Parmar

unread,
Nov 6, 2018, 4:03:33 PM11/6/18
to PowerMock
[For anyone looking at this post because of the same issue].
This worked for me:
      spy(Util.class);
      doCallRealMethod().when(Util, "method", any());
Reply all
Reply to author
Forward
0 new messages