2

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)
DanGordon
  • 671
  • 3
  • 8
  • 26

2 Answers2

8

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)
Schmick
  • 210
  • 2
  • 11
  • Also just bumped into this. Worth mentioning that you `championList` must be wrapped with `Mockito.spy()` earlier for this error to happen. When using a non-wrapped object, the error does not happen. Also, you can store the result of `getChampion(1)` in a variable to circumvent the error being triggered. – Philzen Feb 10 '22 at 02:34
  • Anyway i believe this is an undocumented error. Just tried with Mockito 4.3.1 and the problem persists. Or can anybody say whether this is actually documented behavior or an issue entry exists for this? – Philzen Feb 10 '22 at 02:36
  • There is actually an [excellent writeup on this behavior](http://speakman.net.nz/blog/2019/04/07/mockito-unfinishedstubbingexception-in-tests/), however it doesn't mention if that was really what the Mockito creators had in mind. Even if this was the intended behavior it may be very helpful to add a hint to the error message regarding this special case. – Philzen Feb 10 '22 at 02:40
2

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)).)

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Wow yes that is exactly the problem. Can't believe I missed that. Not sure who wrote that code. It is odd that the exception is later on, but when I commented out `PowerMockito.when(task, "saveDoPatchFile");`, there was no error anymore – DanGordon Jun 26 '14 at 15:14