【问题标题】:Embedded Redis for Spring Boot用于 Spring Boot 的嵌入式 Redis
【发布时间】: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 {

}

【问题讨论】:

  • 是的,我检查过了,但我有点困惑,我的意思是我只想知道我是否必须创建 @Bean RedisServer getserver(){} 来注入它?

标签: java redis spring-boot


【解决方案1】:

您可以使用嵌入式 Redis,例如 https://github.com/kstyrc/embedded-redis

  1. 将依赖项添加到您的 pom.xml 中
  2. 调整您的集成测试的属性以指向您的嵌入式 redis,例如:

    spring:
      redis:
        host: localhost
        port: 6379
    
  3. 在仅在您的测试中定义的组件中实例化嵌入式 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-redisgithub.com/kstyrc/embedded-redis 的继承者,我使用 ozimov/embedded-redis 添加了一个额外的答案。
  • @Renjith 关于密码,我可以使用.setting("requirepass " + redisPassword) 成功设置它。这是 ozimov 版本
【解决方案2】:

您可以使用 ozimov/embedded-redis 作为 Maven(-test) 依赖项(这是 kstyrc/embedded-redis 的继承者)。

  1. 将依赖项添加到您的 pom.xml

    <dependencies>
      ...
      <dependency>
        <groupId>it.ozimov</groupId>
        <artifactId>embedded-redis</artifactId>
        <version>0.7.1</version>
        <scope>test</scope>
      </dependency>
    
  2. 为您的集成测试调整您的应用程序属性

    spring.redis.host=localhost
    spring.redis.port=6379
    
  3. 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
    }

}

它应该可以顺利运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2018-05-28
    • 2013-11-23
    • 2020-09-18
    • 1970-01-01
    • 2016-12-28
    • 2021-07-14
    相关资源
    最近更新 更多