import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.TestPropertySource;
@SpringBootTest
@TestPropertySource(properties = "logging.level.root=INFO")
public class ApplicationTests {
@SpyBean
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void test() {
stringRedisTemplate.opsForValue().set("foo", "bar");
}
}
$ gradle test
> Task :test
2023-04-28T12:49:50.113+08:00 WARN 31995 --- [ionShutdownHook] d.r.c.l.LettucePoolingConnectionProvider : LettucePoolingConnectionProvider contains unreleased connections
BUILD SUCCESSFUL in 3s
3 actionable tasks: 3 executed
here is minimal test project warning.zip
Comment From: wilkinsona
I don't think this is specific to @SpyBean. The same problem occurs with a direct call to Mockito.spy:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@Testcontainers
public class ApplicationTests {
@Container
static RedisContainer redis = new RedisContainer();
@Autowired
private StringRedisTemplate stringRedisTemplate;
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.redis.host", redis::getHost);
registry.add("spring.data.redis.port", redis::getFirstMappedPort);
}
@Test
void test() {
stringRedisTemplate.opsForValue().set("foo", "bar");
}
@TestConfiguration
static class RedisConfiguration {
@Bean
static BeanPostProcessor redisConnectionFactorySpy() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof LettuceConnectionFactory) {
return Mockito.spy(bean);
}
return bean;
}
};
}
}
static class RedisContainer extends GenericContainer<RedisContainer> {
public RedisContainer() {
super("redis:4.0.14");
addExposedPorts(6379);
}
}
}
I suspect it's due to an interaction between Mockito and Lettuce. Unfortunately, without any evidence to suggest that the problem's caused by Spring Boot we can't justify spending any more time on investigating the root cause. If you can provide a minimal example that shows the problem is somehow specific to Spring Boot we can re-open the issue and take another look.