Wednesday, March 11, 2015

Mockito RuntimeException: test should never throw an exception to this level

So I was writing some tests with junit and mockito and started getting the following error after a few tests:

java.lang.RuntimeException: test should never throw an exception to this level
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.ja
va:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegate
Impl.java:127)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.ja
va:82)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44Runn
erDelegateImpl.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:122)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    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:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

After doing some googleing I found that there aren't a lot of useful resources for figuring out why I'm seeing this particular error.
I decided to try and narrow it down. I removed all tests but the one that was throwing this error. Ran the tests and everything passed as expected. Great, that wasn't much help, so I started adding tests back in one at a time and found that it was a combination of two tests that would make things start failing. So after comparing the tests I realized what was wrong. I'm mocking a few classes on the test class level, which is fine as long as the mockito.when()'s don't overlap. The two tests that caused the failure happened to have a call to mockito.when() on the same mock and function. So to fix my problems all I had to do was call a mockito.reset() on the mocks and now all my tests run and I don't get the RunTimeException anymore.

Thursday, February 26, 2015

PowerMockito: java.lang.RuntimeException: PowerMock internal error

java.lang.RuntimeException: PowerMock internal error
    at org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing$InvokeStubMethod.invoke(DelegatingToConstructorsOngoingStubbing.java:133)
    at org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.thenThrow(DelegatingToConstructorsOngoingStubbing.java:71)


I was working on some tests for a project that required the use of PowerMock and Mockito when in one of my tests I started getting the above error.

The test code looks something like this:
@Test 
public void testThrowIOException() throws Exception
{

    File file = mock(File.class);
    when(file.getAbsolutePath()).thenReturn("name.gz");
    IOException exception = new IOException("test message");
       PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenThrow(exception);
       
    try
    {

        Service service = new Service();
        service.method(file);
        fail("expected exception");
    }
    catch(Exception e)
    {
        assertTrue(e.getMessage().contains("test message"));
    }

}

After banging my head on the wall and after several hundred google searches which resulted in nothing I decided to just start tweaking things. The first thing I tried was to change the line
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenThrow(exception);
to
PowerMockito.whenNew(FileInputStream.class).withArguments(file).thenThrow(exception);
I did that since the code I'm testing does actually take an argument, I originally thought that since for the tests sake it didn't matter what the argument was I would use the AnyArguments method, but for some reason changing it to the method that takes arguments fixed my problem and let my tests complete successfully.

Unfortunately I'm not familiar enough with the underlying code to know or easily figure out why the first version caused problems but I think it's obvious that something about how the mock was created without the argument caused the exception and creating the mock with the argument addressed that issue.