org.mockito.exceptions.misusing.UnfinishedStubbingException Unfinished stubbing detected

霸气de小男生 提交于 2019-12-10 11:26:01

问题


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?


回答1:


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);
    }
}



回答2:


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.



来源:https://stackoverflow.com/questions/28437313/org-mockito-exceptions-misusing-unfinishedstubbingexception-unfinished-stubbing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!