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

oxf4rvwz  于 2024-01-06  发布在  Redis
关注(0)|答案(1)|浏览(152)

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

  1. @Slf4j
  2. @AllArgsConstructor
  3. public class redisWriter {
  4. /**
  5. * The connection used to connect to Elasticache.
  6. */
  7. private final StatefulRedisConnection<byte[], byte[]> elasticacheConnection;
  8. /**
  9. * Metric Util for publishing custom metrics.
  10. */
  11. private MetricsUtil metricsUtil;
  12. public void putRecord(final byte[] key, final byte[] value, final int ttlSeconds) {
  13. final Duration ttlDuration = Duration.ofSeconds(ttlSeconds);
  14. final SetArgs ttlSetArgs = SetArgs.Builder.ex(ttlDuration);
  15. final long startTime = System.currentTimeMillis();
  16. this.elasticacheConnection
  17. .async()
  18. .set(key, value, ttlSetArgs)
  19. .whenComplete((msg, exception) -> {
  20. this.metricsUtil.elasticacheInteractionTime("PutRecord", startTime);
  21. if (exception != null) {
  22. if (exception instanceof RedisCommandTimeoutException) {
  23. this.metricsUtil.elasticacheTimeout();
  24. } else if (exception instanceof RedisException) {
  25. log.error("Something went wrong putting in a record", exception);
  26. this.metricsUtil.elasticacheError("PutRecord");
  27. }
  28. }
  29. });
  30. }
  31. }

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

krcsximq

krcsximq1#

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

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

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

  1. @Test
  2. public void testPutRecordTimeout() {
  3. this.haveRedisSetFailWithException(new RedisCommandTimeoutException("timeout"));
  4. this.elasticacheWriterDao.putRecord(KEY, VALUE, TTL_SECONDS);
  5. Mockito.verify(this.mockKdrsMetricUtil, times(1)).elasticacheTimeout();
  6. Mockito.verify(this.mockKdrsMetricUtil, times(1))
  7. .elasticacheInteractionTime(eq(ELASTICACHE_PUT_RECORD), anyLong());
  8. }
  9. private void haveRedisSetFailWithException(@Nonnull final Throwable exception) {
  10. final AsyncCommand<byte[], byte[], String> asyncReturnStringCommand =
  11. new AsyncCommand<>(this.mockRedisReturnStringCommand);
  12. asyncReturnStringCommand.completeExceptionally(exception);
  13. Mockito.when(this.mockRedisAsyncCommands.set(eq(KEY), eq(VALUE), this.setArgsArgumentCaptor.capture()))
  14. .thenReturn(asyncReturnStringCommand);
  15. }


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

展开查看全部

相关问题