Is it possible to verify a mock method running in different thread in Mockito?

kuhajeyan picture kuhajeyan · Jun 20, 2013 · Viewed 25.3k times · Source

I have a method like the following,

public void generateCSVFile(final Date billingDate) {
    asyncTaskExecutor.execute(new Runnable() {
        public void run() {
            try {
                accessService.generateCSVFile(billingDate);
            } catch (Exception e) {
                LOG.error(e.getMessage());
            }
        }
    });
}

I have mocked:

PowerMockito.doNothing().when(accessService).generateCSVFile(billingDate);

But when I verify:

verify(rbmPublicViewAccessService, timeout(100).times(1)).generateCSVFile(billingDate);

It gives me as not invoked. Is this because it is invoked via separate thread, and is it possible to verify the methods called in different thread?

Answer

Tom Verelst picture Tom Verelst · Jun 20, 2013

It is very likely that the Runnable hasn't been executed yet by the asyncTaskExecutor when you verify the invocation, resulting in a verification error in your unit test.

The best way to fix this is to join on the generated thread and wait for execution before verifying the invocations.

If you cannot get the instance of the thread, a possible work around is to mock the asyncTaskExecutor and implement it so it will execute the runnable directly.

private ExecutorService executor;

@Before
public void setup() {
    executor = mock(ExecutorService.class);
    implementAsDirectExecutor(executor);
}

protected void implementAsDirectExecutor(ExecutorService executor) {
    doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation) throws Exception {
            ((Runnable) invocation.getArguments()[0]).run();
            return null;
        }
    }).when(executor).submit(any(Runnable.class));
}