用于 Spring Boot 的嵌入式 Redis
Posted
技术标签:
【中文标题】用于 Spring Boot 的嵌入式 Redis【英文标题】:Embedded Redis for Spring Boot 【发布时间】:2015-12-08 01:23:17 【问题描述】:我在机器上的本地 Redis 服务器的帮助下使用 Spring Boot 运行我的集成测试用例。
但我想要一个嵌入式 Redis 服务器,它不依赖于任何服务器,可以在任何环境中运行,例如 H2 内存数据库。我该怎么做?
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@IntegrationTest("server.port:0")
@SpringApplicationConfiguration(classes = Application.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MasterIntegrationTest
【问题讨论】:
你检查了吗github.com/kstyrc/embedded-redis 是的,我检查过了,但我有点困惑,我的意思是我只想知道我是否必须创建 @Bean RedisServer getserver() 来注入它? 【参考方案1】:您可以使用嵌入式 Redis,例如 https://github.com/kstyrc/embedded-redis
-
将依赖项添加到您的 pom.xml 中
调整您的集成测试的属性以指向您的嵌入式 redis,例如:
spring:
redis:
host: localhost
port: 6379
在仅在您的测试中定义的组件中实例化嵌入式 redis 服务器:
@Component
public class EmbededRedis
@Value("$spring.redis.port")
private int redisPort;
private RedisServer redisServer;
@PostConstruct
public void startRedis() throws IOException
redisServer = new RedisServer(redisPort);
redisServer.start();
@PreDestroy
public void stopRedis()
redisServer.stop();
【讨论】:
有没有办法为嵌入式服务器设置密码? 可能,查看github项目的文档,它似乎是相当可配置的 该项目似乎不再积极维护。上一次发布大约是两年前。 github.com/ozimov/embedded-redis 是github.com/kstyrc/embedded-redis 的继承者,我使用 ozimov/embedded-redis 添加了一个额外的答案。 @Renjith 关于密码,我可以使用.setting("requirepass " + redisPassword)
成功设置它。这是 ozimov 版本【参考方案2】:
您可以使用 ozimov/embedded-redis 作为 Maven(-test) 依赖项(这是 kstyrc/embedded-redis 的继承者)。
将依赖项添加到您的 pom.xml
<dependencies>
...
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.7.1</version>
<scope>test</scope>
</dependency>
为您的集成测试调整您的应用程序属性
spring.redis.host=localhost
spring.redis.port=6379
在test configuration中使用嵌入式redis服务器
@TestConfiguration
public static class EmbededRedisTestConfiguration
private final redis.embedded.RedisServer redisServer;
public EmbededRedisTestConfiguration(@Value("$spring.redis.port") final int redisPort) throws IOException
this.redisServer = new redis.embedded.RedisServer(redisPort);
@PostConstruct
public void startRedis()
this.redisServer.start();
@PreDestroy
public void stopRedis()
this.redisServer.stop();
【讨论】:
这个也不维护!! (【参考方案3】:另一种巧妙的方法是使用testcontainers 库,它可以在 Docker 容器中运行任何类型的应用程序,Redis 也不例外。我最喜欢的是它与 Spring Test 生态系统轻耦合。
maven的依赖:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>$testcontainers.version</version>
</dependency>
简单的集成测试:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "management.port=0")
@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
@DirtiesContext
public abstract class AbstractIntegrationTest
private static int REDIS_PORT = 6379;
@ClassRule
public static GenericContainer redis = new GenericContainer("redis:5-alpine").withExposedPorts(REDIS_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
@Override
public void initialize(ConfigurableApplicationContext ctx)
// Spring Boot 1.5.x
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(ctx,
"spring.redis.host=" + redis.getContainerIpAddress(),
"spring.redis.port=" + redis.getMappedPort(REDIS_PORT));
// Spring Boot 2.x.
TestPropertyValues.of(
"spring.redis.host:" + redis.getContainerIpAddress(),
"spring.redis.port:" + redis.getMappedPort(REDIS_PORT))
.applyTo(ctx);
从 Spring Framework 5.2.5 (Spring Boot 2.3.x) 开始,您可以使用强大的 DynamicPropertySource
注解。
这是一个例子:
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class AbstractIT
static GenericContainer redisContainer = new GenericContainer("redis:5-alpine").withExposedPorts(6379);
@DynamicPropertySource
static void properties(DynamicPropertyRegistry r) throws IOException
r.add("spring.redis.host", redisContainer::getContainerIpAddress);
r.add("spring.redis.port", redisContainer::getFirstMappedPort);
【讨论】:
有没有办法根据我们正在使用的测试容器库知道redis容器镜像名称?【参考方案4】:你可以看到这个存储库:https://github.com/caryyu/spring-embedded-redis-server,与 Spring 和 Spring Boot 完全集成
maven 依赖
<dependency>
<groupId>com.github.caryyu</groupId>
<artifactId>spring-embedded-redis-server</artifactId>
<version>1.1</version>
</dependency>
spring boot 注释
@Bean
public RedisServerConfiguration redisServerConfiguration()
return new RedisServerConfiguration();
application.yml的用法
spring:
redis:
port: 6379
embedded: true
【讨论】:
Repository 文档是中文的,如果你找到英文版的请发链接。 这个项目基本上是已接受答案中提到的项目的包装。无意义【参考方案5】:如果您正在使用弹簧并对access data with redis reactively 做出反应。
这意味着您有一个ReactiveRedisConnectionFactory
(带有一个RedisConnectionFactory
bean)和一个LettuceConnectionFactory
,那么您可能希望按照这种方法为多个测试类设置一个嵌入式redis。
首先将playtika embedded redis 添加到您的依赖项中:
dependencies
testCompile("com.playtika.testcontainers:embedded-redis:2.0.9")
然后在 application.yml 中将 redis 主机和端口设置为 embedded.redis
(由嵌入式 redis 在创建时作为 env 变量生成)。
spring:
redis:
host: \$embedded.redis.host:localhost
port: \$embedded.redis.port:6739
在bootstrap-redisnoauth.properties
文件中,设置环境变量embedded.redis.requirepass=false
,使其不需要密码。
然后在您的测试中使用活动配置文件:
@ActiveProfiles("redisnoauth")
并确保在您的测试类中也包含此 @TestConfiguration
,以便将您连接到在随机生成的端口上生成的 redis。
@Category(IntegrationTest.class)
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("redisnoauth")
public class RedisCacheTest
@TestConfiguration
static class RedisTestConfiguration
@Bean
public RedisConnectionFactory redisConnectionFactory(@Value("$spring.redis.host") String host,
@Value("$spring.redis.port") int port)
return new LettuceConnectionFactory(host, port);
@Bean
public RedisOperations<String, String> stringKeyAndStringValueRedisOperations(RedisConnectionFactory redisConnectionFactory)
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer(UTF_8));
redisTemplate.setValueSerializer(new StringRedisSerializer(UTF_8));
return redisTemplate;
@Test
public void myTest()
// your test
它应该可以顺利运行。
【讨论】:
以上是关于用于 Spring Boot 的嵌入式 Redis的主要内容,如果未能解决你的问题,请参考以下文章
用于生产的外部容器中的 Spring Boot 嵌入式容器或 war 文件
带有嵌入式 Tomcat 的 Spring Boot 忽略了方法角色