I have a class thats a wrapper around the Lettuce Redis client that puts objects into redis and records a few metrics when the future completes inside of its whenComplete. The class under test looks like so,
@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");
}
}
});
}
}
My problem is how do I test the interactions with metricsUtil? I want to make sure that the error handling is correct in the unit tests but I have not figured out a good method for doing so. The restriction that is killing me is I can't just return the future and force it complete in the unit test, I need the future to complete itself without more interaction then just calling putRecord. Is this possible to do with Mockito or will I need to do some refactoring?
I was able to get it working by having the mocks return complete futures like so
in the setups, and as a example of how to get it to throw a exception,
So its completed before it the test even starts in earnest.