redis 如何测试Futures `whenComplete`方法内部的交互

oxf4rvwz  于 12个月前  发布在  Redis
关注(0)|答案(1)|浏览(129)

我有一个类,它是Letterfly Redis客户端的 Package 器,它将对象放入redis中,并在whenComplete中的future完成时记录一些指标。测试中的类看起来像这样,

@Slf4j
@AllArgsConstructor
public class redisWriter {

    /**
     * The connection used to connect to Elasticache.
     */
    private final StatefulRedisConnection<byte[], byte[]> elasticacheConnection;

    /**
     * Metric Util for publishing custom metrics.
     */
    private MetricsUtil metricsUtil;

    public void putRecord(final byte[] key, final byte[] value, final int ttlSeconds) {
        final Duration ttlDuration = Duration.ofSeconds(ttlSeconds);
        final SetArgs ttlSetArgs = SetArgs.Builder.ex(ttlDuration);
        final long startTime = System.currentTimeMillis();

        this.elasticacheConnection
                .async()
                .set(key, value, ttlSetArgs)
                .whenComplete((msg, exception) -> {
                    this.metricsUtil.elasticacheInteractionTime("PutRecord", startTime);
                    if (exception != null) {
                        if (exception instanceof  RedisCommandTimeoutException) {
                            this.metricsUtil.elasticacheTimeout();
                        } else if (exception instanceof RedisException) {
                            log.error("Something went wrong putting in a record", exception);
                            this.metricsUtil.elasticacheError("PutRecord");
                        }
                    }
                });
    }
}

字符串
我的问题是如何测试与metricsUtil的交互?我想确保单元测试中的错误处理是正确的,但我还没有找到一个好的方法来做到这一点。让我头疼的限制是我不能在单元测试中返回future并强制它完成,我需要future在没有更多交互的情况下完成自己,然后只调用putRecord。这可以用Mockito来完成吗?或者我需要做一些重构?

krcsximq

krcsximq1#

我可以让它工作,让模拟返回完整的期货,

final AsyncCommand<byte[], byte[], String> asyncReturnStringCommand =
                new AsyncCommand<>(this.mockRedisReturnStringCommand);
        asyncReturnStringCommand.complete("OK");
        Mockito.when(this.mockRedisAsyncCommands.set(eq(KEY), eq(VALUE), this.setArgsArgumentCaptor.capture()))
                .thenReturn(asyncReturnStringCommand);

字符串
在设置中,作为一个如何让它抛出异常的例子,

@Test
    public void testPutRecordTimeout() {
        this.haveRedisSetFailWithException(new RedisCommandTimeoutException("timeout"));

        this.elasticacheWriterDao.putRecord(KEY, VALUE, TTL_SECONDS);

        Mockito.verify(this.mockKdrsMetricUtil, times(1)).elasticacheTimeout();
        Mockito.verify(this.mockKdrsMetricUtil, times(1))
                .elasticacheInteractionTime(eq(ELASTICACHE_PUT_RECORD), anyLong());
    }

    private void haveRedisSetFailWithException(@Nonnull final Throwable exception) {
        final AsyncCommand<byte[], byte[], String> asyncReturnStringCommand =
                new AsyncCommand<>(this.mockRedisReturnStringCommand);
        asyncReturnStringCommand.completeExceptionally(exception);
        Mockito.when(this.mockRedisAsyncCommands.set(eq(KEY), eq(VALUE), this.setArgsArgumentCaptor.capture()))
                .thenReturn(asyncReturnStringCommand);
    }


在此之前,它已经完成了测试,甚至开始认真。

相关问题