The above mock is only available in the current thread. Is there any way to make it available globally?
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.
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