当尝试清除 Redis 中的数据进行单元测试时,flushAll() 会无休止地运行

问题描述 投票:0回答:2

我有一个带有 Redis 缓存的 kotlin spring 数据应用程序。我想清理 Redis 数据库并使用

redisConnectionFactory.connection.serverCommands().flushAll()
命令。当我单独运行单元测试时,一切正常,没有任何问题。但是,当我尝试运行应用程序中的所有测试(大约有 200 个)甚至来自任何类的测试时,在通过 8 个测试后,所有内容都冻结在命令上
redisConnectionFactory.connection.serverCommands().flushAll()
(我添加了用于调试的日志,我明白了这一点从中)。等待是没有用的,我必须停止测试。不依赖测试;这可以通过不同的测试为不同的班级重现。

也许有人遇到过这种情况,至少可以给我一个提示吗?或者如果有人可以给我建议如何以不同的方式解决我清除缓存的问题,我也会非常感激。

@SpringBootTest
@ExtendWith(SpringExtension::class)
@Import(TestChannelBinderConfiguration::class)
@ContextConfiguration(initializers = [RedisInitializer::class])
@RecordApplicationEvents
abstract class AbstractIntegrationTest {
    @Autowired
    protected lateinit var redisConnectionFactory: RedisConnectionFactory


    @AfterEach
    fun clean() {
        redisConnectionFactory.connection.serverCommands().flushAll()
    }
}

Redis初始化器:

class RedisInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {

    override fun initialize(context: ConfigurableApplicationContext) {
        TestPropertyValues.of(
            "spring.redis.host=" + REDIS_CONTAINER.host,
            "spring.redis.port=" + REDIS_CONTAINER.getMappedPort(REDIS_PORT)
        ).applyTo(context.environment)
    }

    companion object {
        private const val REDIS_PORT = 6379
        private val IMAGE_NAME = DockerImageName.parse("redis:6.2-alpine")
        var REDIS_CONTAINER: GenericContainer<*> = GenericContainer<Nothing>(IMAGE_NAME)
            .withExposedPorts(REDIS_PORT)

        init {
            REDIS_CONTAINER.start()
        }
    }
}

Redis配置:

@Configuration
@EnableCaching
class RedisConfig(
    val redisProperties: RedisProperties
) {
    @Bean
    fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> =
        RedisTemplate<String, Any>().apply {
            setConnectionFactory(connectionFactory)
            setDefaultSerializer(StringRedisSerializer())
            setValueSerializer(redisSerializer())
        }

    @Bean
    fun redisSerializer(): RedisSerializer<Any> {
        val objectMapper = ObjectMapper().apply {
            setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
        }
        return Jackson2JsonRedisSerializer(Any::class.java)
            .apply {
                setObjectMapper(objectMapper)
            }
    }

    @Bean
    fun jedisConnectionFactory(): RedisConnectionFactory {
        val jedisConnectionFactory = if (redisProperties.sentinel != null) {
            JedisConnectionFactory(getSentinelConfiguration())
        } else {
            JedisConnectionFactory(getStandaloneConfiguration())
        }
        jedisConnectionFactory.afterPropertiesSet()
        return jedisConnectionFactory
    }

    private fun getSentinelConfiguration(): RedisSentinelConfiguration {
        val sentinelConfiguration = RedisSentinelConfiguration()
        sentinelConfiguration.setMaster(redisProperties.sentinel.master)
        sentinelConfiguration.password = RedisPassword.of(redisProperties.password)
        sentinelConfiguration.sentinelPassword = RedisPassword.of(redisProperties.sentinel.password)
        sentinelConfiguration.setSentinels(
            redisProperties.sentinel.nodes.stream().map { node: String ->
                val nodeConf = node.split(":").toTypedArray()
                RedisNode(nodeConf[0], nodeConf[1].toInt())
            }.collect(Collectors.toList())
        )
        return sentinelConfiguration
    }

    /**
     * Standalone is used only in integration tests 
     * when raising the application context and connecting 
     * to the Redis docker image from the test container.
     */
    private fun getStandaloneConfiguration(): RedisStandaloneConfiguration {
        val configuration = RedisStandaloneConfiguration()
        configuration.hostName = redisProperties.host
        configuration.port = redisProperties.port
        configuration.password = RedisPassword.of(redisProperties.password)
        return configuration
    }
}
kotlin unit-testing redis jedis
2个回答
0
投票

我用

RedisConnectionFactory
替换了
RedisTemplate
,它对我有帮助:

@SpringBootTest
@ExtendWith(SpringExtension::class)
@Import(TestChannelBinderConfiguration::class)
@ContextConfiguration(initializers = [RedisInitializer::class])
@RecordApplicationEvents
abstract class AbstractIntegrationTest {
    @Autowired
    protected lateinit var redisTemplate: RedisTemplate<String, Any>


    @AfterEach
    fun clean() {
        redisTemplate.execute { connection: RedisConnection ->
            connection.serverCommands().flushDb()
            null
        }
    }
}


0
投票

此命令

redisConnectionFactory.connection.serverCommands().flushAll()
应该耗尽连接池。这就是为什么你只成功运行了 8 次(显然池配置最多有 8 个连接)

怎么样:

try(var connection = redisConnectionFactory.getConnection()) {
    connection.serverCommands().flushDb()
} 

它保证连接将被释放。

© www.soinside.com 2019 - 2024. All rights reserved.