GhostCat
GhostCat

Reputation: 140427

How to prevent Mockito mocking ... dynamically?

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 ;-(");
    }
}

Upvotes: 1

Views: 1338

Answers (2)

Alex Filatov
Alex Filatov

Reputation: 5052

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 ;-(");
    }
}

Upvotes: 2

Tom Bulgur
Tom Bulgur

Reputation: 176

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?

Upvotes: 1

Related Questions