By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account
  • The mockito message in the stacktrace have useful information, but it didn't help
  • The problematic code (if that's possible) is copied here;
    Note that some configuration are impossible to mock via Mockito
  • Provide versions (mockito / jdk / os / any other relevant information)
  • Provide a Short, Self Contained, Correct (Compilable), Example of the issue
    (same as any question on stackoverflow.com)
  • Read the contributing guide
  • Mockito v3.4.0

    Mockito.mockStatic() mocks method seems to be working in the current thread only. I need the static mock to be available globally in multiple threads.

    for e.g:

    try ( MockedStatic<LegacyTextUtils> utilMock = Mockito.mockStatic(LegacyTextUtils.class)){
        utilMock.when(LegacyTextUtils::getReqText).thenReturn("test-123");
    

    The above mock is only available in the current thread. Is there any way to make it available globally?

    Add way to mock static method in multiple threads Mocked static method are not avaiable in other threads Dec 13, 2020 Mocked static method are not avaiable in other threads Mocked static method are not available in other threads Dec 13, 2020 Mocked static method are not available in other threads Mocked static methods are not available in other threads Dec 13, 2020

    Same problem here. As workaround you can mock ExecutorServices, but probably it will not work with all code. Need to be analysed case by case.

    This workaround worked for me. Thanks @bastiao !

    Executor executor = you executor....;
    doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation)
            throws Exception {
            Object[] args = invocation.getArguments();
            Runnable runnable = (Runnable)args[0];
            try (MockedConstruction<SomeClass> mockedConstructor = Mockito.mockConstruction(SomeClass.class);
                  MockedStatic<SomeStaticUtil> mockedUtil = mockStatic(SomeStaticUtil.class))
                ....do mocks things
                runnable.run();
            return null;
    }).when(executor).execute(any());
        @Test
        public void testForMockStaticUsing() {
            log.info("Async to Avoid MockitoException [static mocking is already registered in the current thread]");
            CompletableFuture.runAsync(() -> testEncrypt_null_or_exception());
            CompletableFuture.runAsync(() -> testDecrypt_null_or_exception());
        @Ignore
        void testEncrypt_null_or_exception() {
            log.info("Mocking");
            Mockito.mockStatic(JWT.class);
            Mockito.when(JWT.create()).thenThrow(new RuntimeException());
        @Ignore
        void testDecrypt_null_or_exception() {
            log.info("Mocking");
            Verification verification = Mockito.mock(Verification.class);
            Mockito.mockStatic(JWT.class);
            Mockito.when(JWT.require(any(Algorithm.class))).thenReturn(verification);
        @Test
        public void testForMockStaticUsing() {
            log.info("Async to Avoid MockitoException [static mocking is already registered in the current thread]");
            CompletableFuture.runAsync(() -> testEncrypt_null_or_exception());
            CompletableFuture.runAsync(() -> testDecrypt_null_or_exception());
        @Ignore
        void testEncrypt_null_or_exception() {
            log.info("Mocking");
            Mockito.mockStatic(JWT.class);
            Mockito.when(JWT.create()).thenThrow(new RuntimeException());
        @Ignore
        void testDecrypt_null_or_exception() {
            log.info("Mocking");
            Verification verification = Mockito.mock(Verification.class);
            Mockito.mockStatic(JWT.class);
            Mockito.when(JWT.require(any(Algorithm.class))).thenReturn(verification);
    

    thanks doesn't seem to work as expected . Failed assertions are not shown if running using async.

    I tripped on this and was heavily surprised by that behavior. I would have expect the default to be the opposite. It really frequent to set expectations on a mock and then use them in threads.

    The fix doesn't seem impossible. Instead of usingDetachedThreadLocal in InlineDelegateByteBuddyMockMaker.mockStatics, we could have an interface that can be per thread or global.

    I would vote the default to be global, but having mockGlobalStatic, mockStatic(MyClass.class, withSettings().scope(GLOBAL) or something similar will fit all needs.

    I have started an implementation but do not want to lose my time if it won't be accepted.

    The base code is here and makes my test pass. Other fails, of course, the idea was just to check if it would work.
    https://github.com/henri-tremblay/mockito/tree/support-static-mocks-in-other-threads

    Workaround by mocking CompletableFuture to run on current thread.
    Anyway, would recommend passing executor via constructor and mocking only executor to run on the same thread.

    Sample code mocking runAsync of CompletableFuture:

    @SuppressWarnings("rawtypes")
    MockedStatic<CompletableFuture>  mockCompletableFuture = mockStatic(CompletableFuture.class, Mockito.CALLS_REAL_METHODS);
    mockCompletableFuture.when(() -> CompletableFuture.runAsync(any()))
            .thenAnswer(
                    new Answer<CompletableFuture<Void>>() {
                        @Override
                        public CompletableFuture<Void> answer(InvocationOnMock invocation)
                                throws Throwable {
                            Executor currentThread = Runnable::run;
                            Runnable runnable = invocation.getArgument(0);
                            return CompletableFuture.runAsync(runnable, currentThread);
    

    Same problem here. As workaround you can mock ExecutorServices, but probably it will not work with all code. Need to be analysed case by case.

    This workaround worked for me. Thanks @bastiao !

    Executor executor = you executor....;
    doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation)
            throws Exception {
            Object[] args = invocation.getArguments();
            Runnable runnable = (Runnable)args[0];
            try (MockedConstruction<SomeClass> mockedConstructor = Mockito.mockConstruction(SomeClass.class);
                  MockedStatic<SomeStaticUtil> mockedUtil = mockStatic(SomeStaticUtil.class))
                ....do mocks things
                runnable.run();
            return null;
    }).when(executor).execute(any());
    

    @cytoe1
    Can anyone help, on this, please?
    https://stackoverflow.com/questions/77891809/mocking-not-working-with-executorservice-submit

    I used a modified version of the above workaround and it worked perfectly, even with the correct return value!

    @BeforeEach
    public void beforeEach() {
        //noinspection unchecked
        when(executorService.submit((Callable<Object>) any())).thenAnswer(invocation -> {
            final Callable<?> callable = invocation.getArgument(0);
            var value = callable.call();
            return CompletableFuture.completedFuture(value);
          IGNITE-22355 TableManagerTest's static mocks from #mockManagersAndCreateTableWithDelay don't work properly
          apache/ignite-3#3843