Refine tests involving async caching support.

Closes #2741
This commit is contained in:
John Blum
2023-10-17 12:49:06 -07:00
parent d499c7c224
commit 31ebe7ea1b
3 changed files with 66 additions and 45 deletions

View File

@@ -15,9 +15,15 @@
*/
package org.springframework.data.redis.cache;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import java.time.Duration;
@@ -26,8 +32,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.redis.connection.ReactiveRedisConnection;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
@@ -41,21 +46,18 @@ import org.springframework.data.redis.core.types.Expiration;
@ExtendWith(MockitoExtension.class)
class DefaultRedisCacheWriterUnitTests {
@Mock private CacheStatisticsCollector mockCacheStatisticsCollector = mock(CacheStatisticsCollector.class);
@Mock
private CacheStatisticsCollector mockCacheStatisticsCollector = mock(CacheStatisticsCollector.class);
@Mock private RedisConnection mockConnection;
@Mock
private RedisConnection mockConnection;
@Mock(strictness = Mock.Strictness.LENIENT) private RedisConnectionFactory mockConnectionFactory;
@Mock private ReactiveRedisConnection mockReactiveConnection;
@Mock(strictness = Mock.Strictness.LENIENT) private TestReactiveRedisConnectionFactory mockReactiveConnectionFactory;
@Mock(strictness = Mock.Strictness.LENIENT)
private RedisConnectionFactory mockConnectionFactory;
@BeforeEach
void setup() {
doReturn(this.mockConnection).when(this.mockConnectionFactory).getConnection();
doReturn(this.mockConnection).when(this.mockReactiveConnectionFactory).getConnection();
doReturn(this.mockReactiveConnection).when(this.mockReactiveConnectionFactory).getReactiveConnection();
}
private RedisCacheWriter newRedisCacheWriter() {
@@ -63,11 +65,6 @@ class DefaultRedisCacheWriterUnitTests {
.withStatisticsCollector(this.mockCacheStatisticsCollector));
}
private RedisCacheWriter newReactiveRedisCacheWriter() {
return spy(new DefaultRedisCacheWriter(this.mockReactiveConnectionFactory, Duration.ZERO, mock(BatchStrategy.class))
.withStatisticsCollector(this.mockCacheStatisticsCollector));
}
@Test // GH-2351
void getWithNonNullTtl() {
@@ -86,9 +83,9 @@ class DefaultRedisCacheWriterUnitTests {
assertThat(cacheWriter.get("TestCache", key, ttl)).isEqualTo(value);
verify(this.mockConnection).stringCommands();
verify(mockStringCommands).getEx(eq(key), eq(expiration));
verify(this.mockConnection).close();
verify(this.mockConnection, times(1)).stringCommands();
verify(mockStringCommands, times(1)).getEx(eq(key), eq(expiration));
verify(this.mockConnection, times(1)).close();
verifyNoMoreInteractions(this.mockConnection, mockStringCommands);
}
@@ -107,12 +104,9 @@ class DefaultRedisCacheWriterUnitTests {
assertThat(cacheWriter.get("TestCache", key, null)).isEqualTo(value);
verify(this.mockConnection).stringCommands();
verify(mockStringCommands).get(eq(key));
verify(this.mockConnection).close();
verify(this.mockConnection, times(1)).stringCommands();
verify(mockStringCommands, times(1)).get(eq(key));
verify(this.mockConnection, times(1)).close();
verifyNoMoreInteractions(this.mockConnection, mockStringCommands);
}
interface TestReactiveRedisConnectionFactory extends ReactiveRedisConnectionFactory, RedisConnectionFactory {}
}

View File

@@ -15,8 +15,10 @@
*/
package org.springframework.data.redis.cache;
import static org.assertj.core.api.Assertions.*;
import static org.awaitility.Awaitility.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.awaitility.Awaitility.await;
import io.netty.util.concurrent.DefaultThreadFactory;
@@ -573,10 +575,16 @@ public class RedisCacheTests {
void retrieveCacheValueUsingJedis() {
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> this.cache.retrieve(this.binaryCacheKey)).withMessageContaining("RedisCache");
.isThrownBy(() -> this.cache.retrieve(this.binaryCacheKey))
.withMessageContaining("RedisCache");
}
@ParameterizedRedisTest // GH-2650
@EnabledOnRedisDriver(RedisDriver.JEDIS)
void retrieveLoadedValueUsingJedis() {
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> this.cache.retrieve(this.binaryCacheKey, () -> CompletableFuture.completedFuture("TEST")))
.isThrownBy(() -> this.cache.retrieve(this.binaryCacheKey, () -> usingCompletedFuture("TEST")))
.withMessageContaining("RedisCache");
}
@@ -611,9 +619,11 @@ public class RedisCacheTests {
usingRedisCacheConfiguration());
DefaultRedisCacheWriter cacheWriter = (DefaultRedisCacheWriter) cache.getCacheWriter();
cacheWriter.lock("cache");
CompletableFuture<String> value = (CompletableFuture<String>) cache.retrieve(this.key);
assertThat(value).isNotDone();
cacheWriter.unlock("cache");
@@ -626,11 +636,12 @@ public class RedisCacheTests {
@EnabledOnRedisDriver(RedisDriver.LETTUCE)
void retrieveReturnsLoadedValue() throws Exception {
RedisCache cache = new RedisCache("cache", usingLockingRedisCacheWriter(), usingRedisCacheConfiguration());
AtomicBoolean loaded = new AtomicBoolean(false);
Person jon = new Person("Jon", Date.from(Instant.now()));
CompletableFuture<Person> valueLoader = CompletableFuture.completedFuture(jon);
RedisCache cache = new RedisCache("cache", usingLockingRedisCacheWriter(), usingRedisCacheConfiguration());
Supplier<CompletableFuture<Person>> valueLoaderSupplier = () -> {
loaded.set(true);
return valueLoader;
@@ -648,15 +659,15 @@ public class RedisCacheTests {
@EnabledOnRedisDriver(RedisDriver.LETTUCE)
void retrieveStoresLoadedValue() throws Exception {
RedisCache cache = new RedisCache("cache", usingLockingRedisCacheWriter(), usingRedisCacheConfiguration());
Person jon = new Person("Jon", Date.from(Instant.now()));
Supplier<CompletableFuture<Person>> valueLoaderSupplier = () -> CompletableFuture.completedFuture(jon);
RedisCache cache = new RedisCache("cache", usingLockingRedisCacheWriter(), usingRedisCacheConfiguration());
cache.retrieve(this.key, valueLoaderSupplier).get();
doWithConnection(
connection -> assertThat(connection.keyCommands().exists("cache::key-1".getBytes(StandardCharsets.UTF_8)))
.isTrue());
doWithConnection(connection ->
assertThat(connection.keyCommands().exists("cache::key-1".getBytes(StandardCharsets.UTF_8))).isTrue());
}
@ParameterizedRedisTest // GH-2650
@@ -674,6 +685,10 @@ public class RedisCacheTests {
assertThat(value).isDone();
}
private <T> CompletableFuture<T> usingCompletedFuture(T value) {
return CompletableFuture.completedFuture(value);
}
private RedisCacheConfiguration usingRedisCacheConfiguration() {
return usingRedisCacheConfiguration(Function.identity());
}

View File

@@ -15,9 +15,16 @@
*/
package org.springframework.data.redis.cache;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import java.util.concurrent.CompletableFuture;
@@ -33,16 +40,18 @@ import org.springframework.data.redis.serializer.RedisSerializationContext.Seria
class RedisCacheUnitTests {
@Test // GH-2650
@SuppressWarnings("unchecked")
void cacheRetrieveValueCallsCacheWriterRetrieveCorrectly() throws Exception {
RedisCacheWriter mockCacheWriter = mock(RedisCacheWriter.class);
when(mockCacheWriter.supportsAsyncRetrieve()).thenReturn(true);
when(mockCacheWriter.retrieve(anyString(), any(byte[].class)))
.thenReturn(CompletableFuture.completedFuture("TEST".getBytes()));
doReturn(true).when(mockCacheWriter).supportsAsyncRetrieve();
doReturn(usingCompletedFuture("TEST".getBytes())).when(mockCacheWriter).retrieve(anyString(), any(byte[].class));
RedisCache cache = new RedisCache("TestCache", mockCacheWriter,
RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(SerializationPair.byteArray()));
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(SerializationPair.byteArray());
RedisCache cache = new RedisCache("TestCache", mockCacheWriter, cacheConfiguration);
CompletableFuture<byte[]> value = (CompletableFuture<byte[]>) cache.retrieve("TestKey");
@@ -54,4 +63,7 @@ class RedisCacheUnitTests {
verifyNoMoreInteractions(mockCacheWriter);
}
private <T> CompletableFuture<T> usingCompletedFuture(T value) {
return CompletableFuture.completedFuture(value);
}
}