[英]Embedded Redis for Spring Boot
我在我机器上的本地 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 {
}
您可以使用嵌入式 Redis,如https://github.com/kstyrc/embedded-redis
调整集成测试的属性以指向嵌入式 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(); } }
您可以使用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
在测试配置中使用嵌入式 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(); } }
另一个巧妙的方法是使用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);
}
}
你可以看到这个仓库: https : //github.com/caryyu/spring-embedded-redis-server ,与 Spring 和 Spring Boot 完全集成
<dependency>
<groupId>com.github.caryyu</groupId>
<artifactId>spring-embedded-redis-server</artifactId>
<version>1.1</version>
</dependency>
@Bean
public RedisServerConfiguration redisServerConfiguration() {
return new RedisServerConfiguration();
}
spring:
redis:
port: 6379
embedded: true
如果您使用 spring 和reactive 来通过redis来访问数据。 这意味着您有一个ReactiveRedisConnectionFactory
(带有一个RedisConnectionFactory
bean)和一个LettuceConnectionFactory
那么您可能希望按照这种方法为多个测试类设置嵌入式 redis。
首先将playtika 嵌入的 redis添加到您的依赖项中:
dependencies {
testCompile("com.playtika.testcontainers:embedded-redis:2.0.9")
}
然后设置Redis的主机和端口作为embedded.redis
一个在你的application.yml(由嵌入式Redis的作为创作环境变量产生)。
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
}
}
它应该工作顺利。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.