如何为以下函数模拟和编写单元测试?我发现为 CompletableFuture 编写单元测试很困难。如果函数在3分钟内没有取消任务,我想在单元测试中抛出异常
private void cancel() throws TimeoutException, ExecutionException, InterruptedException {
try {
CompletableFuture.supplyAsync(() -> {
try {
cancelTask();// function that cancels a task
} catch (ApiException ex) {
Logger.error("Api exception while cancelling a tasks")
}
return null
}).get(3, TimeUnit.MINUTES);
} catch (final InterruptedException | ExecutionException | TimeoutException e) {
throw e;
}
}
要在调用 cancelTask() 后强制 CompletableFuture.supplyAsync 在单元测试用例中返回超时异常,您必须在测试此用例时重写 cancelTask。您可以通过多种方式做到这一点:
商务舱
@Slf4j
@AllArgsConstructor
public class TaskManager {
private final int cancelTimeoutInMillis;
public void cancel() throws TimeoutException, ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> {
try {
cancelTask();// function that cancels a task
} catch (ApiException ex) {
log.error("Api exception while cancelling a tasks");
}
return null;
}).get(cancelTimeoutInMillis, TimeUnit.MILLISECONDS);
}
@StandardException
public static class ApiException extends RuntimeException {
}
protected void cancelTask() {
//cancel the task
}
}
测试班:
@Slf4j
class TaskManagerTest {
@Test
public void testCancel() throws Exception {
// Create the CompletableFuture under test
TaskManager manager = new TaskManager(500) {
@Override
protected void cancelTask() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
};
// Verify that the expected exception is thrown
Assertions.assertThatThrownBy(manager::cancel).isInstanceOf(TimeoutException.class);
}
}
商务课程
@AllArgsConstructor
@Getter
public class TaskExecutor {
private final int cancelTimeoutInMillis;
public void cancelTask() throws TaskManager.ApiException {
}
}
@Slf4j
@AllArgsConstructor
public class TaskManager {
private final TaskExecutor taskExecutor;
public void cancel() throws TimeoutException, ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> {
try {
taskExecutor.cancelTask();// function that cancels a task
} catch (ApiException ex) {
log.error("Api exception while cancelling a tasks");
}
return null;
}).get(taskExecutor.getCancelTimeoutInMillis(), TimeUnit.MILLISECONDS);
}
@StandardException
public static class ApiException extends RuntimeException {
}
}
测试班
@Slf4j
class TaskManagerTest {
@Test
public void testCancel() throws Exception {
// Create the CompletableFuture under test
TaskExecutor taskExecutor = new TaskExecutor(500){
@Override
public void cancelTask() throws TaskManager.ApiException {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
};
TaskManager manager = new TaskManager(taskExecutor);
// Verify that the expected exception is thrown
Assertions.assertThatThrownBy(manager::cancel).isInstanceOf(TimeoutException.class);
}
}