Можно ли проверить метод макета, выполняющийся в другом потоке в 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);
Он дает мне, как не вызываемый. Это потому, что он вызывается через отдельный поток, и можно ли проверить методы, вызываемые в разных потоках?
Ответы
Ответ 1
Очень вероятно, что Runnable
еще не был выполнен asyncTaskExecutor
при проверке вызова, в результате чего в вашей unit test.
Лучший способ исправить это - присоединиться к сгенерированному потоку и дождаться выполнения перед проверкой вызовов.
Если вы не можете получить экземпляр потока, возможная работа заключается в том, чтобы издеваться над asyncTaskExecutor
и реализовать его, чтобы он выполнял runnable напрямую.
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));
}
Ответ 2
У меня была такая же проблема и играли с аргументом таймаута
http://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Mockito.html#22
но с аргументом 0, как в
verify(someClass, timeout(0)).someMethod(any(someParameter.class));
И это работает. Я предполагаю, что тестовый поток дает, и, следовательно, другой поток имеет возможность выполнить свою работу, соответствующим образом называя макеты.
Тем не менее он пахнет хаком.
Ответ 3
Для дальнейшей итерации ответа Тома - используя Java 8 Lambdas, теперь вы можете использовать следующий код для насмешки над Executor, который немного более лаконичен:
doAnswer((Answer<Void>)invocation -> {
((Runnable)invocation.getArgument(0)).run();
return null;
}).when(executorService).submit(any(Runnable.class));