首页 > 解决方案 > Java 的 ListenableFuture 和 addListener 回调的单元测试

问题描述

我有一个模块,该模块具有将数据写入 Kinesis 流的方法。我们称之为反馈流。

我想对在 ListenableFuture 的结果上调用的分析服务函数运行验证单元测试,我尝试设置模拟,但遇到 ClassCast 异常。我想我可能错误地设置了模拟。

我想单元测试的方法:

public void writeData(KinesisRecord kinesisRecord, Response response) {

    FeedbackRecord feedbackRecord = new 
    FeedbackRecord(kinesisRecord.getVersion(), kinesisRecord.getNotificationId(), response.name(), 
kinesisRecord.getDestination());

    Gson g = new Gson();
    byte[] dataBytes = g.toJson(feedbackRecord).getBytes(StandardCharsets.UTF_8);
    ListenableFuture<UserRecordResult> future = kinesisProducer.addUserRecord(streamName, kinesisRecord.getNotificationId(), ByteBuffer.wrap(dataBytes));

    future.addListener(() -> {
    try {
        UserRecordResult userRecordResult = future.get();
        analyticsService.trackSuccess(AnalyticsConstants.FeedbackProducer.WRITE_SUCCESS, AnalyticsConstants.FeedbackProducer.WRITEDATA_LOCATION + " " + userRecordResult.getSequenceNumber());
        log.debug("Write to Kinesis Feedback successful, record sequence number: " + userRecordResult.getSequenceNumber());
    } catch (InterruptedException e) {
        e.printStackTrace();
        analyticsService.trackError(AnalyticsConstants.FeedbackProducer.WRITE_ERROR, AnalyticsConstants.FeedbackProducer.WRITEDATA_LOCATION);
        log.error("Feedback Kinesis Write failed: " + e);
    } catch (ExecutionException e) {
        e.printStackTrace();
        analyticsService.trackError(AnalyticsConstants.FeedbackProducer.WRITE_ERROR, AnalyticsConstants.FeedbackProducer.WRITEDATA_LOCATION);
        log.error("Feedback Kinesis Write failed: " + e);
    }
}, MoreExecutors.directExecutor());

单元测试尝试:

@Test
public void addUserRecordFutureTest() throws ExecutionException, InterruptedException {

    ListenableFuture<UserRecordResult> responseFuture = mock(ListenableFuture.class);

    Attempt attempt = new Attempt(1, 2, "AttemptError", "5xx", true);
    List<Attempt> attempts = new ArrayList<>();
    attempts.add(attempt);
    UserRecordResult mockUserRecordResult = mock(UserRecordResult.class);

    when(kinesisProducer.addUserRecord(any(), any(), any())).thenReturn(responseFuture);
    doAnswer(invocation -> {
        ListenableFutureCallback listenableFutureCallback = invocation.getArgument(0);
        listenableFutureCallback.onSuccess(mockUserRecordResult);
    // do asserts here
        return null;
    }).when(responseFuture).addListener(any(), any());

    feedbackProducer.writeData(mockRecord, FeedbackProducer.Response.invalid_channel);
}

堆栈跟踪:

在此处输入图像描述

标签: javaunit-testingjava-8mockitofuture

解决方案


推荐阅读