### Question:
ThreadAsyncExecutor implements AsyncExecutor { @Override public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException { if (!asyncResult.isCompleted()) { asyncResult.await(); } return asyncResult.getValue(); }  @Override AsyncResult<T> startProcess(Callable<T> task); @Override AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback); @Override T endProcess(AsyncResult<T> asyncResult);  }### Answer:
@Test void testEndProcess() throws Exception { assertTimeout(ofMillis(5000), () -> { final var executor = new ThreadAsyncExecutor(); final var result = new Object(); when(task.call()).thenAnswer(i -> { Thread.sleep(1500); return result; }); final var asyncResult = executor.startProcess(task); assertNotNull(asyncResult); assertFalse(asyncResult.isCompleted()); try { asyncResult.getValue(); fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); } catch (IllegalStateException e) { assertNotNull(e.getMessage()); } assertSame(result, executor.endProcess(asyncResult)); verify(task, times(1)).call(); assertTrue(asyncResult.isCompleted()); assertSame(result, executor.endProcess(asyncResult)); verifyNoMoreInteractions(task); }); }
@Test public void testEndProcess() throws Exception { assertTimeout(ofMillis(5000), () -> { final ThreadAsyncExecutor executor = new ThreadAsyncExecutor(); final Object result = new Object(); final Callable<Object> task = mock(Callable.class); when(task.call()).thenAnswer(i -> { Thread.sleep(1500); return result; }); final AsyncResult<Object> asyncResult = executor.startProcess(task); assertNotNull(asyncResult); assertFalse(asyncResult.isCompleted()); try { asyncResult.getValue(); fail("Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task"); } catch (IllegalStateException e) { assertNotNull(e.getMessage()); } assertSame(result, executor.endProcess(asyncResult)); verify(task, times(1)).call(); assertTrue(asyncResult.isCompleted()); assertSame(result, executor.endProcess(asyncResult)); verifyNoMoreInteractions(task); }); }