Search code examples
powermockpowermockito

Cannot mock/spy final class using PowerMockito.spy()


I'm trying to use PowerMockito to create a spy of a final class but I keep getting the following error, even though I am using PowerMockito's spy() method in place of Mockito's:

java.lang.IllegalArgumentException: Cannot subclass final class class com.whoever.WidgetUploadClient

My test case looks something like this:

...
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(RobolectricTestRunner.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest(WidgetUploadClient.class)
@Config(manifest=Config.NONE, sdk = 23)
public class WidgetUploadClientTest {
    @Test
    public void testUploadWidget() {
        WidgetMarshaller mockMarshaller = mock(WidgetMarshaller.class);
        WidgetUploadClient client = spy(new WidgetUploadClient(mockMarshaller)); // Exception thrown by spy()
        ...
    }
}

Shouldn't @PrepareForTest(WidgetUploadClient.class) and using PowerMockito's spy() method account for WidgetUploadClient being final?

I have also tried the alternative approach found in Robolectric's PowerMock guide: using RobolectricTestRunner or RobolectricGradleTestRunner as the test runner (@RunWith) with @Rule public PowerMockRule rule = new PowerMockRule(). When I do that, the test fails to run entirely and a different exception is thrown.

I am using PowerMock/PowerMockito 1.6.5, Robolectric 3.1 and Java 1.8.0_91-b14.


Solution

  • I believe that I am using the APIs correctly but am experiencing by a bug that effects developers trying to use the combination of Robolectric and PowerMock. For reference, the bug can be tracked on Robolectric's issue tracker. The combination of libraries has been broken since at least January 2016 (currently ~6 months ago.)