I have wrote following code:
@RunWith(PowerMockRunner.class)
@PrepareForTest(Integer.class)
public class TestClass{
@Test
public void test(){
PowerMockito.mockStatic(Integer.class);
when(Integer.parseInt(anyString())).thenReturn(0);
System.out.println(Integer.parseInt("12"));
}
}
I got following error message :
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.ctc.dime.services.autopublisher.stores.StoresPublishingServiceTest.test(StoresPublishingServiceTest.java:120)
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 org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:291)
at org.powermock.api.mockito.internal.invocationcontrol.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:193)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:168)
b.....
What do I wrong?
You should prepare the class that uses the system class, and not the system class itself. See https://code.google.com/p/powermock/wiki/MockSystem
EDIT
See the Powermock FAQ:
I cannot mock classes in from java.lang, java.net, java.io or other
system classes, why?
This is because they're loaded by Java's bootstrap classloader and cannot be
byte-code manipulated by PowerMock's classloader. Since
PowerMock 1.2.5 there's a work-around, please have a look at this
simple example to see how it's done.
I made a small test, and it seems to be working for java.lang.String but not for java.lang.Integer for whatever reason. See the classes below. The first method fails. The second with String.format works. This seems to be a Powermock bug for me.
The third method is my usual workaround to avoid static or system mocking. I just create a package protected method, and I spy it in my test. I recommend the same. It is better than involving Powermock.
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Dummy.class } )
public class TestClass{
@Test
public void testStaticIntegerMocking(){
PowerMockito.mockStatic(Integer.class);
when(Integer.parseInt(anyString())).thenReturn(0);
System.out.println(Dummy.parseInt("12"));
}
@Test
public void assertThatMockingStringWorks() throws Exception {
PowerMockito.mockStatic(String.class);
final String string = "string";
final String args = "args";
final String returnValue = "returnValue";
when(String.format(string, args)).thenReturn(returnValue);
final Dummy systemClassUser = new Dummy();
assertEquals(systemClassUser.format(string, args), returnValue);
}
@Test
public void testSpying(){
Dummy dummy = new Dummy();
dummy = spy(dummy);
doReturn( 0 ).when(dummy).parseIntToBeSpyed(anyString());
System.out.println(dummy.parseIntToBeSpyed("12"));
}
}
The Dummy class:
import java.io.IOException;
public class Dummy {
public static Integer parseInt( String string ) {
return Integer.parseInt(string);
}
public String format(String one, String args) throws IOException {
return String.format(one, args);
}
public Integer parseIntToBeSpyed( String string ) {
return Integer.parseInt(string);
}
}
It seems the method might already have been mocked.
Commenting out the "Integer.parseInt" method interception line has worked fine for me:
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Integer.class } )
public class TestClass{
@Test
public void testStaticIntegerMocking() {
PowerMockito.mockStatic(Integer.class);
// when(Integer.parseInt(anyString())).thenReturn(new Integer(10023));
System.out.println("Hello..."+Integer.parseInt("12"));
}
@Test
public void testStaticIntegerMocking2() {
PowerMockito.mockStatic(Integer.class);
when(Integer.decode(anyString())).thenReturn(new Integer(10023));
System.out.println("HelloX..."+Integer.decode("#ffff"));
}
}
It seems "0" is the default mock result in such a case.
Please notice: if you return a "new Integer(...)" the test will execute with no errors, but still "0" will be returned, even if we specify a different value, as e.g. new Integer("1002").
But wait, there's more! A similar test worked fine, exactly as it would expected, with static method "Integer.decode(String)"! See the second method above.