Reputation: 879
Suppose I have a two classes that work together to execute a callable like this:
public class blah {
@Autowired
private ExecutorServiceUtil executorServiceUtil;
@Autowired
private RestTemplate restClient;
public SomeReturnType getDepositTransactions(HttpHeaders httpHeaders) {
ExecutorService executor = executorServiceUtil.createExecuter();
try {
DepositTransactionsAsyncResponse asyncResponse = getPersonalCollectionAsyncResponse( httpHeaders, executor);
// do some processing
// return appropriate return type
}finally {
executorServiceUtil.shutDownExecutor(executor);
}
}
Future<ResponseEntity<PersonalCollectionResponse>> getPersonalCollectionAsyncResponse( HttpHeaders httpHeaders, ExecutorService executor) {
PersonalCollectionRequest personalCollectionRequest = getpersonalCollectionRequest(); // getPersonalCollectionRequest populates the request appropriately
return executor.submit(() -> restClient.exchange(personalCollectionRequest, httpHeaders, PersonalCollectionResponse.class));
}
}
public class ExecutorServiceUtil {
private static Logger log = LoggerFactory.getLogger(ExecutorServiceUtil.class);
public ExecutorService createExecuter() {
return Executors.newCachedThreadPool();
}
public void shutDownExecutor(ExecutorService executor) {
try {
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.error("Tasks were interrupted");
}
finally {
if (!executor.isTerminated()) {
log.error("Cancel non-finished tasks");
}
executor.shutdownNow();
}
}
}
How can I use Mockito to stub the a response and return it immediately?
I've tried the below but my innovcation.args() returns [null]
PowerMockito.when(executor.submit(Matchers.<Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>> any())).thenAnswer(new Answer<FutureTask<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>>() {
@Override
public FutureTask<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>> answer(InvocationOnMock invocation) throws Throwable {
Object [] args = invocation.getArguments();
Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>> callable = (Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>) args[0];
callable.call();
return null;
}
});
Upvotes: 0
Views: 2302
Reputation: 140427
You do that by not using your ExecutorServiceUtil
in your test code. What I mean is: you provide a mock of that util class to your production code!
And that mock does return a "same thread executor service"; instead of a "real service" (based on a thread pool). Writing such a same-thread-executor is actually straight forward - see here.
In other words: you want two different unit tests here:
ExecutorServiceUtil
class in isolation; make sure it does the thing it is supposed to do (where I think: checking that it returns a non-null ExecutorService is almost good enough!)blah
class ... that use a mocked service. And all of a sudden, all your problems around "it is async" go away; because the "async" part vanishes in thin air.Upvotes: 1