使用 Redis 进行集成测试

Posted

技术标签:

【中文标题】使用 Redis 进行集成测试【英文标题】:Integration Testing with Redis 【发布时间】:2013-04-07 07:14:36 【问题描述】:

在 Jedis 库的帮助下,我开始在我的项目中使用 Redis。一切正常,但现在我有一个问题,我的功能测试需要 Redis 启动,我想在我的持续集成中避免这种情况。最好的方法是什么?

【问题讨论】:

你能把你所有的 jedis 调用封装在一个 DAO 中以抽象出 redis 吗?然后,当您运行单元测试时,注入该 DAO 的测试实现,该实现返回某种固定数据。 是的,抽象是我想做的事情,对于单元测试,我可以模拟与 Redis 的连接,但对于集成测试,我正在寻找解决方案。例如。 cassandra 有一种我们使用的嵌入式 cassandra。 啊,很有趣 - 不确定 Redis 是否有类似的东西。对于我的集成测试,我们使用特定于 CI 环境的 redis 实例和特定的配置覆盖来指示测试应该针对该虚拟 redis 实例运行。 【参考方案1】:

我已经为 Java 实现了一个简单的 redis 嵌入式运行器: https://github.com/kstyrc/embedded-redis

目前,*nix 使用 redis 2.6.14,Windows 使用https://github.com/MSOpenTech/redis。但是,您可以利用 RedisServer 类来运行您自己的运行脚本。

我计划扩展实现以支持 RedisConf(bind、slaveof、port、dbfilename 等)。在此之后,我会将 jar 上传到 clojars 以供 mvn deps 使用。

【讨论】:

当我在 pom.xml 中添加您在 README.md 中指定的依赖项 sn-p 时,它说它找不到依赖项。我还添加了存储库 sn-p。到目前为止,您的代码托管在哪里? 我尝试使用您的嵌入式 redis 项目无济于事:这是一篇与我的困境有关的帖子:***.com/questions/29059794 @NishantKelkar 也许你应该刷新 maven?神器在那里:clojars.org/repo/redis/embedded/embedded-redis/0.5 @kstyrc 你能重新开始在 jar 上积极工作吗【参考方案2】:

以下是功能/集成测试的几个选项:

    只需在 CI 服务器上启动一个 redis 实例。所有测试都将负责在执行后进行适当的清理。 尝试以某种方式控制 redis 进程,即在 CI 服务器上使用一些 shell 脚本或作业在运行测试之前/之后启动/停止它。至少从测试中消除了一些设置/清理的负担,因为对于每个独立的构建,您都将拥有独立的 redis 设置。 通过使用一些内存解决方案(如您为 cassandra 提到的解决方案(如果存在))进一步控制 redis。

要提一提的是,集成测试不应该取代单元测试。单元测试可能应该是首选,它们可以涵盖更多情况,而集成测试可以用来检查应用程序的所有部分是否可以很好地协同工作。我认为这就是很多人选择第一选项的原因。

这是一个类似的问题about mongodb 答案有一个指向适用于第二个选项的项目的链接(控制 mongodb 进程)如果您点击项目页面上的一些相关链接,那么还有一个叫做 nosql-unit 的东西。我认为这个试图涵盖选项三。我没有使用它,但看起来它也为redis 提供了一些东西。

【讨论】:

【参考方案3】:

您可以通过命令行在任意端口上启动 Redis 服务器:redis-server --port 7777。因此,出于集成测试的目的,您可以在可用(或随机)端口上启动 Redis,确保 Jedis 已配置为使用该端口。

这样,您就有了一个“新鲜”的 Redis 实例,您知道它不会与任何其他进程发生冲突,包括同时发生的其他测试运行。这与我能想到的运行内存/嵌入式数据库进行集成测试的类比非常接近。

要使用“预设数据”预加载 Redis,请使用 --dbfilename <file> 开关:redis-server --port 7777 --dbfilename test.rdb

【讨论】:

【参考方案4】:

试试nosql-unit。它支持使用java进行redis单元测试。

我试过EmbeddedRedis,发现很多Jedis接口都不支持。因此,使用 EmbbededRedis 并不是一个好主意,尤其是当您使用一些高级 redis 功能(如“管道”)时。

我建议使用 ManagedRedis 进行单元测试:

    从redis.io 下载redis 源代码到您的测试资源中 在 $(your-redis-dir)/src 中构建一个 redis-server 使用 ManagedRedis 编写单元测试,这里是 example。注意“REDIS_HOME”是你的redis代码下载的目录,ManagedRedis会在$REDIS_HOME/src中找到redis-server 运行单元测试。

【讨论】:

如果你推荐一个库,习惯上会展示它是如何应用的。请在您的答案中添加一些示例代码。【参考方案5】:

正如@ksytrc 在his answer 中提到的,我基本上使用了他的解决方案。它在this project 中工作。您只需要添加嵌入式redis 依赖项。

        <dependency>
            <groupId>com.github.kstyrc</groupId>
            <artifactId>embedded-redis</artifactId>
            <version>0.6</version>
            <scope>test</scope>
        </dependency>

然后在测试类中定义redisServer

RedisServer redisServer;

    @Before
    public void setUp() throws IOException 
        redisServer = new RedisServer();
        redisServer.start();
    

还可以使用以下凭据定义 application.yml

spring:
  redis:
    host: localhost
    port: 6379

【讨论】:

【参考方案6】:

我可以处理同样问题的更好方法是创建一个处理RedisTemplate 的 Spring 服务。之后,我只使用@MockBean 来模拟服务并抽象出在我的测试期间缺少运行的 Redis 实例。

举例:

@Service
class RedisService 

    @Autowired
    private RedisTemplate<String, SomeClass> redisTemplate;

    SomeClass get(String key) 
        return redisTemplate.opsForValue().get(key);
    


在集成测试中:

class IntegrationTest 

    @MockBean
    private RedisService redisService;

    @Before
    public void setup() 
        SomeClass someClass= new SomeClass();
        when(redisService.get(anyString())).thenReturn(someClass);
    



我对使用一些 redis 内存数据库解决方案持怀疑态度,因为我了解实际的替代方案并不是 Spring 团队“官方”推荐的。

【讨论】:

以上是关于使用 Redis 进行集成测试的主要内容,如果未能解决你的问题,请参考以下文章

尚融宝14-集成redis缓存

使用Mybatis和不同DB进行集成测试开发时如何做集成测试

使用 Airflow 进行集成测试

集成测试

使用 Flyway 进行集成测试

使用 Jooq 进行集成测试