Asynchroner Aufrufer des Services
public class AsychronousServiceCaller implements Service {
@Inject
private Service service;
@Inject
private ExecutorService executorService;
public void doIt(final String argument) {
executorService.submit(() -> {
service.doIt(argument);
});
}
}
Der asynchrone Aufrufer ist ein Delegate, das einen ExecutorService nutzt, um den Service aufzurufen. Dabei wird das Argument direkt durchgereicht.
Der Test
@ExtendWith(MockitoExtension.class)
class AsychronousServiceCallerTest {
@Mock
private Service mockService;
@Mock
private ExecutorService mockExecutorService;
@InjectMocks
private AsychronousServiceCaller asychronousServiceCaller;
@Test
public void doIt_serviceIsCalledAsynchronously() throws Exception {
ArgumentCaptor<Runnable> captor = forClass(Runnable.class);
asychronousServiceCaller.doIt("");
verify(mockExecutorService).submit(captor.capture());
verify(mockService, times(0)).doIt(any());
captor.getValue().run();
verify(mockService, times(1)).doIt(any());
}
@Test
public void doIt_serviceIsCalledWithPassedArgument() throws Exception {
String argument = "FOO";
ArgumentCaptor<Runnable> captor = forClass(Runnable.class);
asychronousServiceCaller.doIt(argument);
verify(mockExecutorService).submit(captor.capture());
captor.getValue().run();
verify(mockService).doIt(eq(argument));
}
}
Die Testklasse umfasst zwei Tests für die in der Einführung genannten Aspekte.
Der erste Test ruft den asynchronen Aufrufer auf und testet, ob der Service erst aufgerufen wird, wenn der ExecutorService dies tut.
Der zweite Test überprüft, ob das Argument richtig an den Service weitergegeben wird. Dazu wird das Lamba, dass an den Executor-Service übergeben wird, abgefangen und dann direkt ausgeführt.
Wie man sieht, ist das Testen von asychronen Aufrufen einfach und alle notwendigen Tools (JUnit, Mockito) sind leicht einzubinden.
(microphone-drop)