I want to verify that when run methodA, my code run through methodB asynchronously (1 time) like below
public class ClassA {
@Inject
@Named("executor")
ExecutionContextExecutor eventHandlerExecutor;
public Object methodA (Object x, Object y) {
...
CompletableFuture.runAsync(() -> methodB(i, j), eventHandlerExecutor);
...
}
public void methodB (Object n, Object m) {
...
}
}
How should I write a unit test for this?
classA.methodA(x, y);
// can spying classA help to verify it?
verify(classA, times(1)).methodB(any(), any());
Yes. You can spy the ClassA
instance you want to test. The nice thing of a spy is that it allows you to test the real thing but at the same time can also let you to verify if certain of its method are really executed or not.
Another nice thing is that it allow you to add some codes that will be executed before actually executing the real method by using doAnswer()
. So you can make use of it to capture the thread name that is used to execute methodB for verification later , and also setup a CountDownLatch
such that the main thread will wait for the aysnc. thread to finish before proceeding.
So something likes as below after combining all of these :
@Test
void test(){
ClassA sut = new ClassA(xxx);
sut = spy(sut);
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<Thread> asyncThreadRef = new AtomicReference();
doAnswer(ans -> {
try {
asyncThreadRef.set(Thread.currentThread());
return ans.callRealMethod();
} finally {
latch.countDown();
}
}).when(sut).methodB(eq(aaa), eq(bbb));
sut.methodA(aaa,bbb);
latch.await(500, TimeUnit.MILLISECONDS);
verify(sut, times(1)).methodB(aaa, bbb);
assertThat(asyncThreadRef.get()).isNotSameAs(Thread.currentThread());
}