1

This is a follow-on question to this one.

My problem is: I upgraded our environment to newer versions of JUnit, Mockito, ... Unfortunately, I was running my local tests with a up-to-date IBM JRE. Then we found out that in our build environment, all our Mockito tests are now failing with

org.mockito.exceptions.base.MockitoException:

Mockito cannot mock this class: interface java.util.concurrent.ExecutorService.

Mockito can only mock non-private & non-final classes. If you're not sure why you're getting this error, please report to the mailing list.

Followed by:

Early IBM virtual machine are known to have issues with Mockito, please upgrade to an up-to-date version.

OK; so I spent some time to A) figure within a test that it is run by an outdated JRE so I could B) then have all tests skipped. In the end; I put together the below code.

But some notes upfront: I verified that my forceJUnit...() method really throws that exception when running with an IBM Java8 JRE that has SR1 or SR2 level. My point is: although the method should throw ... when I run that test case, I am still hitting the Mockito exception about "can not mock"!

Any idea what I am doing wrong here?

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

class Helper {
    public static void forceJUnitToIgnoreTestForJava8SR1() {
        Assume.assumeFalse("Ignoring test when running with JRE SR1", isJava8SR1());
    }

    private static boolean isJava8SR1() {
        String fullVersion = System.getProperty("java.fullversion", "");
        return fullVersion.contains("R28_Java8_SR1");
    }
}

@RunWith(MockitoJUnitRunner.class)
public class Mcve {

    @Mock
    private ExecutorService service;

    @Before
    public void setup() {
        Helper.forceJUnitToIgnoreTestForJava8SR1();

        // make the mcve do something
        doAnswer(new Answer<Future<?>>() {
            @Override
            public Future<?> answer(InvocationOnMock invocation) throws Throwable {
                return null;
            }
        }).when(service).submit(any(Runnable.class));
    }

    @Test
    public void test() {
        System.out.println("won't show up ;-(");
    }
}
Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248

2 Answers2

2

Directly call MockitoAnnotations.initMocks(this) instead of using MockitoJUnitRunner:

public class Mcve {

    @Mock
    private ExecutorService service;

    @Before
    public void setup() {
        Helper.forceJUnitToIgnoreTestForJava8SR1();
        MockitoAnnotations.initMocks(this);
        ...
    }

    @Test
    public void test() {
        System.out.println("won't show up ;-(");
    }
}
Alex Filatov
  • 4,768
  • 2
  • 16
  • 10
  • Nice, that works, too! But it would force me to update **two** different locations within my test cases; whereas the other option just requires to **insert** something. Besides, I am already halfway through making all the required updates; but still: +1. – GhostCat Jan 20 '17 at 15:26
1

Not sure here, but:

  • Maybe you just try to call Helper.forceJUnitToIgnoreTestForJava8SR1(); within a method marked with @BeforeClass
  • Or, you could change your test case and remove the @Mock annotation; and do ALL of the required configuration steps AFTER calling Helper.forceJUnitToIgnoreTestForJava8SR1(); within your setup method?
Tom Bulgur
  • 176
  • 1
  • 7
  • Oh, that was quick ... and honestly ... err ... straight forward. Using @BeforeClass works just fine (the other option would not have been an option; as I dont have just one mcve, but 50+ pretty complex testcases that have this problem)! – GhostCat Jan 20 '17 at 15:03