NullPointerException when calling mocked method - java

I try to mock a final method (readChar of class DataInputStream):
MyClassTest
#RunWith(PowerMockRunner.class)
#PrepareForTest(DataInputStream.class)
public class MyClassTest {
#Test
public void testMyMethod() throws IOException {
DataInputStream mockStream = PowerMockito.mock(DataInputStream.class);
Mockito.when(mockStream.readChar()).thenReturn('a');
System.out.println(mockStream.readChar()); // OK (print 'a')
Assert.assertEquals('a', MyClass.myMethod(mockStream));
}
}
MyClass
public class MyClass {
public static char myMethod(DataInputStream dis) throws IOException {
return dis.readChar(); // NPE raises
}
}
It works when calling the mocked method in testMyMethod() but in myMethod() NullPointerException raises, why?
EDIT :
The complete failure trace :
java.lang.NullPointerException
at java.io.DataInputStream.readChar(Unknown Source)
at test.test.MyClass.myMethod(MyClass.java:8)
at test.test.MyClassTest.testMyMethod(MyClassTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

First this code is a mock antipattern : Don't mock types you don't own! (see this answer on StackOverflow)
Second, DataInputStream is a class of the JDK PowerMock cannot use the same hacky classloader that modifies byte code.
For that there's a solution and two possible tricks :
use the interface
encapsulate the call in a class that you own, then prepare this class instead, documented here at google code, or even better make your own mockable class (without the need of powermock)
use an agent, documented here at google code
The first option is clearly the very best, and the first two options also allows one to avoid this mock antipattern.

DataInputStream is a 'system' class from JVM which is probably already loaded by JVM.
#PrepareForTest would have to remove final modifier from the methods (to be able to mock), but it can't do so for already-loaded classes (HotSpot JVM doesn't support class signature changes for already-loaded classes), and this is probably why you get this exception.
Luckily there's also DataInput interface implemented by DataInputStream - maybe you can try mocking not DataInputStream but DataInput, for this you don't even need PowerMock, just Mockito.

Related

PowerMockRunner Initialization Error

I'm trying to use PowerMockito to mock a static class throwing an IOException. I'm using JUnit 4.12 and PowerMockMockito 1.6.3 in my package. However, I get an "initializationError" due to the "#RunWith(PowerMockRunner.class)" annotation I need to put above the class definition. This happens even if the test class is empty.
Here is the stack trace of the error:
org.powermock.reflect.exceptions.FieldNotFoundException: Field 'fTestClass' was not found in class org.junit.internal.runners.MethodValidator.
at org.powermock.reflect.internal.WhiteboxImpl.getInternalState(WhiteboxImpl.java:581)
at org.powermock.reflect.Whitebox.getInternalState(Whitebox.java:308)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validateTestMethods(PowerMockJUnit4MethodValidator.java:97)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validateInstanceMethods(PowerMockJUnit4MethodValidator.java:67)
at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:51)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.<init>(PowerMockJUnit44RunnerDelegateImpl.java:70)
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 org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:156)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:61)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
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 org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
My attempts to solve the problem has led me to several older SO questions like this one, where a similar problem was resolved after PowerMockito was updated to 1.6.1. Unfortunately it was not very helpful.
I am new to PowerMockito, so I might be missing something too obvious to be mentioned in any guides. Any ideas on how I can resolve this? Thanks in advance.
If the whole thing is your code, then a not so subtle solution would be:
avoid PowerMock, and this sort of problems completely. Instead accept that static is an abnormality in good OO designs - as it leads to direct, hard coupling of your classes.
So instead of writing hard-to-test code that requires the big Powermock hammer in order to be testable: come up with code that avoids static; and that thus can be tested without the need for Powermock.
Long story short: learn about writing testable code (for example by listening to these [videos][1]). And let the door to the Powermock room closed. And when that static thingy lives in external code that you don't own; you might still put a wrapper around it and avoid the direct dependency.
Edit: of course, it is cumbersome to work around such a central thing as Apache commons, but still, you can always do something like:
class TheStaticThing {
public static Whatever doSomething(Somethin els) throws StupidException { ...
you can forward and "interface" this:
interface TheStaticThingFunctionality {
public static Whatever doSomething(Somethin els) throws StupidException;
Then you have a simple
class TheStaticThingImpl implements TheStaticThingFunctionality {
#Override
public Whatever doSomething(Somethin els) throws StupidException {
return TheStaticThing.doSomething(els);
}
And, now within your client class:
class Client {
private final TheStaticThingFunctionality func;
Client() { this(new TheStaticThingImpl()); }
Client(TheStaticThingFunctionality func) { this.func = func; }
This code allows you:
keep using the existing static methods with minimal overhead
pass mocked instances of TheStaticThingFunctionality into your Client class
And now you can fully control when you exceptions to fly; and more importantly: you already made a first step towards decoupling yourself from the implementation provided by Apachace commons - as you are now free to exchange TheStaticThingImpl with something else if you see a need for that!

ClassCastException exception when running 2 Roboelectic test-classes with Power Mock that mocks the same static class

I have 2 test-classes: MyTest1 and MyTest2. They both have the same header and test the same class but they test 2 very different aspects of that class (you may criticize me for that but let us not discuss that here):
#RunWith(LocalRobolectricTestRunner.class)
#Config(manifest = RobolectricTestData.AndroidManifestFileName)
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest(MyStrangeClassWithStaticMethods.class)
#ParametersAreNonnullByDefault
public class MyTest1 extends MyBaseTest {
// This is to dinamically load PowerMock. We can't use PowerMockRunner because we already use
// RobolectricTestRunner and PowerMockRunner doesn't do robolectric's stuff.
#Rule
public final PowerMockRule rule = new PowerMockRule();
/**
* Tests set up.
*/
#Before
public final void setUp() throws Exception {
super.setUp();
}
public void testSomething() {
PowerMockito.mockStatic(MyStrangeClassWithStaticMethods.class);
// do some stuff
}
}
The problem is that I can run separately MyTest1 and all tests go OK. I can run separately MyTest2 and all tests go OK. But when I run all tests of both MyTest1 and MyTest2 (they are compiled into one jar) - when I do this, only first run class (MyTest1) goes OK and the second class fails.
All tests crash with this exception:
org.mockito.exceptions.base.MockitoException:
ClassCastException occurred while creating the mockito proxy :
class to imposterize : 'com.my.project.MyStrangeClassWithStaticMethods', loaded by classloader : 'org.powermock.core.classloader.MockClassLoader#2617b42c'
imposterizing class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$$41f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader#230eec25'
proxy instance class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$$41f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader#23a0547b'
You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:109)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:57)
at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
at com.my.project.MyTest2.testSomething(MyTest2.java:66666<no matter what line number>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:52)
at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:638)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.chromium.testing.local.GtestComputer$GtestSuiteRunner.run(GtestComputer.java:46)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.chromium.testing.local.JunitTestMain.main(JunitTestMain.java:105)
Caused by: java.lang.ClassCastException: Cannot cast com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$$41f09512 to com.my.project.MyStrangeClassWithStaticMethods
at java.lang.Class.cast(Class.java:3176)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
... 47 more
This crash forces me to merge my 2 classes into 1 test class. And this probably blocks me a possibility to mock MyStrangeClassWithStaticMethods.class in another test class. I can mock it only once :(
The issue looks like ClassCastException exception when running Robolectric test with Power Mock on multiple files but a little different and needs another solution.
Powermock 1.6.0
Mockito 1.10.5
Robolectric 3.0
I found a solution. The stack trace says:
disabling the Objenesis cache might help (see MockitoConfiguration)
I did it and it worked. Just add this class to your tests source location:
package org.mockito.configuration;
public class MockitoConfiguration extends DefaultMockitoConfiguration {
#Override
public boolean enableClassCache() {
return false;
}
}

Mockito UnfinishedStubbingException with when().thenReturn()

I am getting the error message Unfinished Stubbing detected here, when running the following code:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.*;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
#RunWith(PowerMockRunner.class)
public class PatchWriterTaskTest {
#Before
public void before() throws Exception {
filePath = getFilePath();
task = PowerMockito.spy(new PatchWriterTask());
patchFilesName = new HashMap<Integer, String>();
patchFilesName.put(1, "TCE_RDF_COVERED_DATA_REGION.sql");
scriptPath = new File(filePath + "do_patch_rdf.sql");
PowerMockito.when(task, "getLogger").thenReturn(logger);
PowerMockito.when(task, "getPatchFilesName").thenReturn(patchFilesName);
PowerMockito.when(task, "getDirectoryPath").thenReturn(filePath);
PowerMockito.when(task, "saveDoPatchFile");
}
#Test
public void testUpdateIssuesTable() throws Exception {
PatchWriterTask task = new PatchWriterTask();
Connection conn = mock(Connection.class);
PreparedStatement updateStatement = mock(PreparedStatement.class);
String sql = "update val_issues set PATCH_CREATION_INFO = ? where VAL_ISSUE_ID = ?";
when(conn.prepareStatement(sql)).thenReturn(updateStatement);
The last line throws the error. It doesn't really make sense, as I have done the same code before. Why am I getting this error?
EDIT: I am using powerMockito in order to use the Whitebox.invokeMethod() method, but I also want to use regular Mockito in the rest of the program. Could that be a problem?
Stack Trace:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:426)
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!
at com.navteq.rdf.base.task.PatchWriterTaskTest.testUpdateIssuesTable(PatchWriterTaskTest.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
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:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
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:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
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:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)
I wanted to add a note that I got this exact same exception, even though my code was written properly. It turned out to be entirely a runtime problem.
My code:
when(service.getChampionById(1, region, null, null)).thenReturn(championList.getChampion(1));
The exception:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at ResourceV1bTest.setUpResources(ResourceV1bTest.java:2168)
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!
It turned out that the following call was throwing an exception, which then triggered the Mockito exception about unfinished stubbing.
championList.getChampion(1)
Seems like the error is pretty clear.
PowerMockito.when(task, "saveDoPatchFile");
...is missing a thenReturn, right?
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();
So why is the exception down in your test method? Neither PowerMock nor Mockito can flag a failure to call thenReturn until the next time you interact with (Power)Mockito or a mock. After all, Mockito and PowerMockito aren't notified that your #Before method ends, and have to accept the "waiting for thenReturn" state. (You're allowed to call mock before thenReturn to allow thenReturn(mock(Foo.class)).)

Mockito swallows up stack trace?

Why does Mockito swallow up stack traces? For example, if I have a
public class Foo
{
public void foo()
{
bar();
}
public void bar()
{
baz();
}
public void baz()
{
throw new RuntimeException();
}
}
and a test such as
public class MockTest
{
#Test
public void test()
{
Mockito.spy(new Foo()).foo();
}
}
the exception thrown always looks like
java.lang.RuntimeException
at Foo.baz(Foo.java:17)
at MockTest.test(MockTest.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)
** So, where is all the stuff between
Foo.baz(Foo.java:17)
MockTest.test(MockTest.java:11)
?
(The example provided here is a just a simplification -- I'm dealing with a lot more indirections, classes, and so forth. I can't have Mockito swallowing up the critical parts of a partial mock stack trace...)
YES, mockito cleans stacktraces !
The piece of code at work StackTraceFilter
There are different ways to disable that
Since Mockito 1.10.10, provide your own StackTraceCleanerProvider via the mockito extension mechanism (create a resource file mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider with the qualified name of your implementation)
Override the cleansStackTrace method in a custom IMockitoConfiguration, look there for more information.
This is the magic of proxies.
The javadoc of [Mockito.spy()][1] states
Creates a spy of the real object. The spy calls real methods unless they are stubbed.
So spy() returns a mock object, which is a proxy. It is a sub class of Foo so it inherits the methods, but it wraps their execution in a interceptor method. This method has a try catch block which catches any exception thrown in the actual method invocation. The catch block then uses a ConditionalStackTraceFilter to clean up the stack trace. To do this, it uses a StackTraceFilter which in the comments of its filter(..) method states
/**
* Example how the filter works (+/- means good/bad):
* [a+, b+, c-, d+, e+, f-, g+] -> [a+, b+, g+]
* Basically removes all bad from the middle. If any good are in the middle of bad those are also removed.
*/
The call stack at the invocation of baz() is something like (super simplified)
at Foo.baz()
at FooPROXY.baz()
at Foo.bar()
at FooPROXY.bar()
at Foo.foo()
at FooPROXY.foo()
at MockTest.test()
All the PROXY stack trace elements, which are the proxies and the interceptors involved, and everything in between get removed. So you get the result you see.
Note that Junit also cleans it up so as not to show its internals.

Mockito + PowerMock LinkageError while mocking system class

I've got such a code snippet:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Thread.class})
public class AllMeasuresDataTest {
#Before
public void setUp() throws Exception {
}
#Test
public void testGetMeasures() {
AllMeasuresData measure = new AllMeasuresData();
assertEquals(measure.getMeasures(), null);
HashMap<String, Measure> map = new HashMap<String, Measure>();
measure.setMeasures(map);
assertEquals(measure.getMeasures(), map);
measure.setMeasures(null);
assertEquals(measure.getMeasures(), null);
}
#Test
public void testAllMeasuresData() throws IOException {
ClassLoader loader = PowerMockito.mock(ClassLoader.class);
Thread threadMock = PowerMockito.mock(Thread.class);
Vector<URL> vec = new Vector<URL>();
Mockito.when(loader.getResources("measure")).thenReturn(vec.elements());
Mockito.when(threadMock.getContextClassLoader()).thenReturn(loader);
PowerMockito.mockStatic(Thread.class);
Mockito.when(Thread.currentThread()).thenReturn(threadMock);
...
}
}
While running this tests I got:
java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:201)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:149)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.initializeMBean(ProtocolImpl.java:247)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.<init>(ProtocolImpl.java:237)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.getInstance(ProtocolImpl.java:185)
at measure.CodeCoverCoverageCounter$6ya5ud0ow79ijrr1dvjrp4nxx60qhxeua02ta2fzpmb1d.<clinit>(MeasureCalculatorsHolder.java:146)
at measure.MeasureCalculatorsHolder.<clinit>(MeasureCalculatorsHolder.java:17)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:188)
at javassist.runtime.Desc.getClassObject(Desc.java:43)
at javassist.runtime.Desc.getClassType(Desc.java:152)
at javassist.runtime.Desc.getType(Desc.java:122)
at javassist.runtime.Desc.getType(Desc.java:78)
at algorithm.AllMeasuresDataTest.testGetMeasures(AllMeasuresDataTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312)
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:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTestInSuper(PowerMockJUnit49RunnerDelegateImpl.java:116)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTest(PowerMockJUnit49RunnerDelegateImpl.java:77)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
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:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
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:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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.codecover.juniteclipse.runner.EclipseTestRunner.main(EclipseTestRunner.java:40)
Do you know how can I prevent this? I maybe there is another way to mock such a piece of code:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
...
Enumeration<URL> resources = classLoader.getResources(path);
Try adding this annotation to your Test class:
#PowerMockIgnore("javax.management.*")
Worked for me.
Similar to the accepted response here, I ended up having to exclude all of the SSL related classes:
#PowerMockIgnore({"javax.management.*", "org.apache.http.conn.ssl.*", "com.amazonaws.http.conn.ssl.*", "javax.net.ssl.*"})
Adding that to the top of my class resolved the error.
Classloader conflict, use this: #PowerMockIgnore("javax.management.*")
Let mock classloader do not load javax.*.
It works.
This may be a bit of an old topic, but I have also ran into this problem. Turns out that some of the java versions cannot handle powermockito when powermock finds out there are 2 classes with the same name in the same package (over different dependencies).
With any version higher than Java 7_25 it gives this error.
In PowerMock 1.7.0 a user-defined global configuration can be added to your project's classpath. PowerMockConfig
org/powermock/extensions/configuration.properties
Simply add a line in the properties file like:
powermock.global-ignore=javax.management.*
This will resolve the error for all the test classes in your project.
In order to mock system classes, prepare the class that is the target of the test, not Thread.class. There's no way PowerMock will be able to instrument Thread.class because it is required during JVM startup - well before PowerMock can instrument.
The way instrumentation works, once a class is loaded, it can no longer be intstrumented.
See the PowerMock wiki.
Depending on your individual setup, it may be necessary to add more methods to #PowerMockIgnore. I stumbled over this with slf4j, for using PowerMock and slf4j together, you'll need
#PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*", "org.w3c.dom.*" })

Categories