Sping Boot 的嵌入式Redis

0dxa2lsx  于 12个月前  发布在  Redis
关注(0)|答案(5)|浏览(198)

我在本地Redis服务器的帮助下,使用Sping Boot 运行了我的集成测试用例。
但是我想要一个嵌入式的Redis服务器,它不依赖于任何服务器,可以在任何环境下运行,就像H2内存数据库一样。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@IntegrationTest("server.port:0")
@SpringApplicationConfiguration(classes = Application.class) 
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MasterIntegrationTest {

}

字符串

sf6xfgos

sf6xfgos1#

你可以使用像https://github.com/kstyrc/embedded-redis这样的嵌入式Redis
1.将依赖项添加到pom.xml
1.调整集成测试的属性,使其指向嵌入的redis,例如:

spring:
  redis:
    host: localhost
    port: 6379

字符串
1.将嵌入式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();
    }
}

ig9co6j1

ig9co6j12#

edit:我现在强烈建议使用testcontainers,如@ magiconter answer中所解释的,我现在也在使用它进行测试。
您可以将ozimov/embedded-redis用作Maven(-test)-dependency(这是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>

字符串
1.为集成测试调整应用程序属性

spring.redis.host=localhost
 spring.redis.port=6379


1.在测试配置中使用嵌入式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();
   }
 }

vawmfj5a

vawmfj5a3#

另一种简洁的方法是使用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(Sping Boot 2.3.x)起,您可以使用强大的DynamicPropertySource annotation。下面是一个示例:

@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);
    }
}

pw9qyyiw

pw9qyyiw4#

你可以看到这个存储库:https://github.com/caryyu/spring-embedded-redis-server,与Spring和Sping 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

eyh26e7m

eyh26e7m5#

如果你正在使用spring和reactive to 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文件中,设置env变量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
    }

}


它应该工作顺利。

相关问题