web-dev-qa-db-ja.com

Mockitoで別のスレッドで実行されているモックメソッドを確認することは可能ですか?

私は次のような方法を持っています、

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

私はあざけりました:

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

しかし、私が確認すると:

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

呼び出されないように私に与えます。これは別のスレッドを介して呼び出されるためであり、別のスレッドで呼び出されたメソッドを確認することは可能ですか?

20
kuhajeyan

呼び出しを検証するときにRunnableasyncTaskExecutorによってまだ実行されていない可能性が高いため、ユニットテストで検証エラーが発生します。

これを修正する最良の方法は、生成されたスレッドに参加し、呼び出しを確認する前に実行を待機することです。

スレッドのインスタンスを取得できない場合、考えられる回避策は、asyncTaskExecutorをモックして実装し、ランナブルを直接実行することです。

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));
}
36
Tom Verelst

同じ問題があり、タイムアウト引数 http://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Mockito.html#22 をいじってみましたが、引数0のような

verify(someClass, timeout(0)).someMethod(any(someParameter.class));

そしてそれは機能します。私は、テストスレッドが生成され、他のスレッドがモックを適切に呼び出して作業を行う機会があると想定しています。それでもハックのようなにおいがします。

11
Francis Martens

トムの答えをさらに繰り返すには、Java 8 Lambdasを使用して、次のコードを使用してエグゼキューターをモックすることができます。これは少し簡潔です。

    doAnswer((Answer<Void>)invocation -> {
        ((Runnable)invocation.getArgument(0)).run();
        return null;
    }).when(executorService).submit(any(Runnable.class));
1
RobinFood