Powermock: UnfinishedStubbingException when mocking constructor (whenNew) and placing return result directly.

Created on 8 Feb 2017  路  1Comment  路  Source: powermock/powermock

public class Creator
{
    Creator create()
    {
        throw new MyException();
    }
}

```java
public class MyException
extends RuntimeException
{
}

```java
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(Creator.class)
public class CreatorTest
{
    @Test(expected = MyException.class)
    public void testThenReturn()
    throws Exception
    {
        Creator creator = new Creator();

        PowerMockito.whenNew(MyException.class)
            .withNoArguments().thenReturn(new MyException());

        creator.create();
    }
}

This test fails with UnfinishedStubbingException. But if I first assign returned exception to a variable

MyException toReturn = new MyException();
PowerMockito.whenNew(MyException.class)
            .withNoArguments().thenReturn(toReturn);

it works as expected.

This is not specific to Exception type of course, but this example illustrates the purpose of creating a variable and not saving it for assertion.

This might be another "trade off", but it's not documented anywhere and I'm just curious why this makes such a difference.

org.mockito:mockito-core:1.10.19
org.powermock:powermock-api-mockito:1.6.2
org.powermock:powermock-module-junit4:1.6.2

Thanks.

Cannot be fixed bug

Most helpful comment

It happens, because then you use new MyException() after whenNew(MyException.class) all calls are intercepted and considered as call to mock object.
So it the same as writewhen(someObject.callMethod()).thenReturn(someObject.callMethod())

But with new call there is one nuance. PowerMock can intercept only modified classes and a test class is modified by default even if it not pointed in @PrepareForTest. Why it was done in such way I cannot say, but if I try to change it some test are failed. Maybe when I'l have enough time I'll investigate the issue.

I suggest you use this small workaround.

>All comments

It happens, because then you use new MyException() after whenNew(MyException.class) all calls are intercepted and considered as call to mock object.
So it the same as writewhen(someObject.callMethod()).thenReturn(someObject.callMethod())

But with new call there is one nuance. PowerMock can intercept only modified classes and a test class is modified by default even if it not pointed in @PrepareForTest. Why it was done in such way I cannot say, but if I try to change it some test are failed. Maybe when I'l have enough time I'll investigate the issue.

I suggest you use this small workaround.

Was this page helpful?
0 / 5 - 0 ratings