Polishing.
Move executor from ClusterConfiguration to connection factories as the executor is a Spring concept that isn't tied to endpoint details or the client config. Reorder static factory methods after constructors and property accessors after static factory methods. Inline single-line single-use methods that aren't intended as extension hooks for easier readability. Disable TaskExecutor disposal on ClusterCommandExecutor.destroy(). Remove NonNull annotations as default non-nullability is defined on the package level. Simplify tests to use integration tests to avoid excessive mocking. See #2594 Original pull request: #2669
This commit is contained in:
@@ -16,12 +16,16 @@
|
||||
package org.springframework.data.redis.connection.jedis;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.data.redis.SettingsUtils;
|
||||
import org.springframework.data.redis.connection.ClusterCommandExecutor;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.test.condition.EnabledOnRedisClusterAvailable;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -93,4 +97,20 @@ class JedisConnectionFactoryIntegrationTests {
|
||||
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test // GH-2594
|
||||
@EnabledOnRedisClusterAvailable
|
||||
void configuresExecutorCorrectly() {
|
||||
|
||||
AsyncTaskExecutor mockTaskExecutor = mock(AsyncTaskExecutor.class);
|
||||
|
||||
JedisConnectionFactory factory = new JedisConnectionFactory(SettingsUtils.clusterConfiguration());
|
||||
factory.setExecutor(mockTaskExecutor);
|
||||
factory.start();
|
||||
|
||||
ClusterCommandExecutor clusterCommandExecutor = factory.getRequiredClusterCommandExecutor();
|
||||
assertThat(clusterCommandExecutor).extracting("executor").isEqualTo(mockTaskExecutor);
|
||||
|
||||
factory.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.jedis;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import redis.clients.jedis.JedisClientConfig;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -37,11 +33,8 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.data.redis.connection.ClusterCommandExecutor;
|
||||
import org.springframework.data.redis.connection.ClusterTopologyProvider;
|
||||
import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisPassword;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
@@ -50,17 +43,12 @@ import org.springframework.data.redis.connection.jedis.JedisConnectionFactory.St
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
|
||||
import redis.clients.jedis.JedisClientConfig;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link JedisConnectionFactory}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
class JedisConnectionFactoryUnitTests {
|
||||
|
||||
@@ -349,41 +337,13 @@ class JedisConnectionFactoryUnitTests {
|
||||
assertThat(connectionFactory.isRunning()).isTrue();
|
||||
}
|
||||
|
||||
@Test // GH-2594
|
||||
void configuresCustomTaskExecutorCorrectly() {
|
||||
|
||||
AsyncTaskExecutor mockTaskExecutor = mock(AsyncTaskExecutor.class);
|
||||
ClusterTopologyProvider mockClusterTopologyProvider = mock(ClusterTopologyProvider.class);
|
||||
JedisCluster mockJedisCluster = mock(JedisCluster.class);
|
||||
|
||||
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
|
||||
|
||||
clusterConfiguration.setAsyncTaskExecutor(mockTaskExecutor);
|
||||
|
||||
JedisConnectionFactory connectionFactory = initSpyedConnectionFactory(clusterConfiguration, null);
|
||||
|
||||
doReturn(false).when(connectionFactory).getUsePool();
|
||||
doReturn(mockJedisCluster).when(connectionFactory).createCluster();
|
||||
doReturn(mockClusterTopologyProvider).when(connectionFactory).createTopologyProvider(eq(mockJedisCluster));
|
||||
|
||||
connectionFactory.start();
|
||||
|
||||
assertThat(connectionFactory.isRunning()).isTrue();
|
||||
|
||||
ClusterCommandExecutor clusterCommandExecutor = connectionFactory.getClusterCommandExecutor();
|
||||
|
||||
assertThat(clusterCommandExecutor).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(clusterCommandExecutor, "executor")).isEqualTo(mockTaskExecutor);
|
||||
}
|
||||
|
||||
private JedisConnectionFactory initSpyedConnectionFactory(RedisSentinelConfiguration sentinelConfiguration,
|
||||
@Nullable JedisPoolConfig poolConfig) {
|
||||
|
||||
// we have to use a spy here as jedis would start connecting to redis sentinels when the pool is created.
|
||||
JedisConnectionFactory connectionFactorySpy = spy(new JedisConnectionFactory(sentinelConfiguration, poolConfig));
|
||||
|
||||
doReturn(null).when(connectionFactorySpy)
|
||||
.createRedisSentinelPool(any(RedisSentinelConfiguration.class));
|
||||
doReturn(null).when(connectionFactorySpy).createRedisSentinelPool(any(RedisSentinelConfiguration.class));
|
||||
|
||||
doReturn(null).when(connectionFactorySpy).createRedisPool();
|
||||
|
||||
@@ -397,8 +357,8 @@ class JedisConnectionFactoryUnitTests {
|
||||
|
||||
JedisConnectionFactory connectionFactorySpy = spy(new JedisConnectionFactory(clusterConfiguration, poolConfig));
|
||||
|
||||
doReturn(clusterMock).when(connectionFactorySpy)
|
||||
.createCluster(any(RedisClusterConfiguration.class), any(GenericObjectPoolConfig.class));
|
||||
doReturn(clusterMock).when(connectionFactorySpy).createCluster(any(RedisClusterConfiguration.class),
|
||||
any(GenericObjectPoolConfig.class));
|
||||
|
||||
doReturn(null).when(connectionFactorySpy).createRedisPool();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import io.lettuce.core.EpollProvider;
|
||||
import io.lettuce.core.KqueueProvider;
|
||||
@@ -36,10 +37,12 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.data.redis.ConnectionFactoryTracker;
|
||||
import org.springframework.data.redis.RedisConnectionFailureException;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
import org.springframework.data.redis.SettingsUtils;
|
||||
import org.springframework.data.redis.connection.ClusterCommandExecutor;
|
||||
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
@@ -570,6 +573,24 @@ class LettuceConnectionFactoryTests {
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test // GH-2594
|
||||
@EnabledOnRedisClusterAvailable
|
||||
void configuresExecutorCorrectly() {
|
||||
|
||||
LettuceClientConfiguration configuration = LettuceTestClientConfiguration.builder().build();
|
||||
AsyncTaskExecutor mockTaskExecutor = mock(AsyncTaskExecutor.class);
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(SettingsUtils.clusterConfiguration(),
|
||||
configuration);
|
||||
factory.setExecutor(mockTaskExecutor);
|
||||
factory.start();
|
||||
|
||||
ClusterCommandExecutor clusterCommandExecutor = factory.getRequiredClusterCommandExecutor();
|
||||
assertThat(clusterCommandExecutor).extracting("executor").isEqualTo(mockTaskExecutor);
|
||||
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test // GH-2503
|
||||
void startStopStartConnectionFactory() {
|
||||
|
||||
|
||||
@@ -15,15 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.redis.connection.ClusterTestVariables.CLUSTER_NODE_1;
|
||||
import static org.springframework.data.redis.connection.RedisConfiguration.WithHostAndPort;
|
||||
import static org.springframework.data.redis.test.extension.LettuceTestClientResources.getSharedClientResources;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.getField;
|
||||
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
|
||||
import static org.springframework.data.redis.connection.RedisConfiguration.*;
|
||||
import static org.springframework.data.redis.test.extension.LettuceTestClientResources.*;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.*;
|
||||
|
||||
import io.lettuce.core.AbstractRedisClient;
|
||||
import io.lettuce.core.ClientOptions;
|
||||
@@ -54,10 +51,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.data.redis.ConnectionFactoryTracker;
|
||||
import org.springframework.data.redis.RedisConnectionFailureException;
|
||||
import org.springframework.data.redis.connection.ClusterCommandExecutor;
|
||||
import org.springframework.data.redis.connection.PoolException;
|
||||
import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisClusterConnection;
|
||||
@@ -1050,8 +1045,7 @@ class LettuceConnectionFactoryUnitTests {
|
||||
clusterConfiguration.clusterNode("localhost", 1234).setMaxRedirects(42);
|
||||
|
||||
LettuceClientConfiguration clientConfiguration = LettuceTestClientConfiguration.builder()
|
||||
.clientOptions(ClusterClientOptions.builder().validateClusterNodeMembership(false).build())
|
||||
.build();
|
||||
.clientOptions(ClusterClientOptions.builder().validateClusterNodeMembership(false).build()).build();
|
||||
|
||||
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfiguration,
|
||||
clientConfiguration);
|
||||
@@ -1246,55 +1240,24 @@ class LettuceConnectionFactoryUnitTests {
|
||||
@Test // GH-2594
|
||||
void createRedisConfigurationWithNullInvalidRedisUriString() {
|
||||
|
||||
Arrays.asList(" ", "", null).forEach(redisUri ->
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> LettuceConnectionFactory.createRedisConfiguration(redisUri))
|
||||
.withMessage("RedisURI must not be null or empty")
|
||||
.withNoCause());
|
||||
Arrays.asList(" ", "", null)
|
||||
.forEach(redisUri -> assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> LettuceConnectionFactory.createRedisConfiguration(redisUri))
|
||||
.withMessage("RedisURI must not be null or empty").withNoCause());
|
||||
}
|
||||
|
||||
@Test // GH-2594
|
||||
void createRedisConfigurationWithValidRedisUriString() {
|
||||
|
||||
RedisConfiguration redisConfiguration =
|
||||
LettuceConnectionFactory.createRedisConfiguration("redis://skullbox:6789");
|
||||
RedisConfiguration redisConfiguration = LettuceConnectionFactory.createRedisConfiguration("redis://skullbox:6789");
|
||||
|
||||
assertThat(redisConfiguration).isInstanceOf(RedisStandaloneConfiguration.class);
|
||||
|
||||
assertThat(redisConfiguration)
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(RedisStandaloneConfiguration.class))
|
||||
.extracting(RedisStandaloneConfiguration::getHostName)
|
||||
.isEqualTo("skullbox");
|
||||
assertThat(redisConfiguration).asInstanceOf(InstanceOfAssertFactories.type(RedisStandaloneConfiguration.class))
|
||||
.extracting(RedisStandaloneConfiguration::getHostName).isEqualTo("skullbox");
|
||||
|
||||
assertThat(redisConfiguration)
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(RedisStandaloneConfiguration.class))
|
||||
.extracting(RedisStandaloneConfiguration::getPort)
|
||||
.isEqualTo(6789);
|
||||
}
|
||||
|
||||
@Test // GH-2594
|
||||
void configuresCustomTaskExecutorCorrectly() {
|
||||
|
||||
AsyncTaskExecutor mockTaskExecutor = mock(AsyncTaskExecutor.class);
|
||||
LettuceConnectionProvider mockConnectionProvider = mock(LettuceConnectionProvider.class);
|
||||
RedisClusterClient mockRedisClient = mock(RedisClusterClient.class);
|
||||
|
||||
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
|
||||
|
||||
clusterConfiguration.setAsyncTaskExecutor(mockTaskExecutor);
|
||||
|
||||
LettuceConnectionFactory connectionFactory = spy(new LettuceConnectionFactory(clusterConfiguration));
|
||||
|
||||
doReturn(mockRedisClient).when(connectionFactory).createClient();
|
||||
doReturn(mockConnectionProvider).when(connectionFactory).createConnectionProvider(eq(mockRedisClient), any());
|
||||
|
||||
connectionFactory.start();
|
||||
|
||||
assertThat(connectionFactory.isRunning()).isTrue();
|
||||
|
||||
ClusterCommandExecutor clusterCommandExecutor = connectionFactory.getClusterCommandExecutor();
|
||||
|
||||
assertThat(getField(clusterCommandExecutor, "executor")).isEqualTo(mockTaskExecutor);
|
||||
assertThat(redisConfiguration).asInstanceOf(InstanceOfAssertFactories.type(RedisStandaloneConfiguration.class))
|
||||
.extracting(RedisStandaloneConfiguration::getPort).isEqualTo(6789);
|
||||
}
|
||||
|
||||
static class CustomRedisConfiguration implements RedisConfiguration, WithHostAndPort {
|
||||
@@ -1342,8 +1305,7 @@ class LettuceConnectionFactoryUnitTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(this.getHostName(), that.getHostName())
|
||||
&& Objects.equals(this.getPort(), that.getPort());
|
||||
return Objects.equals(this.getHostName(), that.getHostName()) && Objects.equals(this.getPort(), that.getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1354,10 +1316,7 @@ class LettuceConnectionFactoryUnitTests {
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return "CustomRedisConfiguration{" +
|
||||
"hostName='" + hostName + '\'' +
|
||||
", port=" + port +
|
||||
'}';
|
||||
return "CustomRedisConfiguration{" + "hostName='" + hostName + '\'' + ", port=" + port + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user