使用Redis进行集成测试

18
我已经开始在项目中使用Redis,并借助Jedis库。一切都运作正常,但现在我的功能测试需要Redis处于启动状态,我希望在持续集成中避免这种情况。有什么最好的方法可以做到这一点吗?

3
你能否将所有 jedis 调用都包装在一个 DAO 中,以抽象出 Redis?然后,在运行单元测试时,注入一个返回某种固定数据的测试 DAO 实现。 - Adam
1
是的,抽象化是我想要做的事情,对于单元测试,我没有问题模拟与Redis的连接,但对于集成测试,我正在寻找解决方案。例如,Cassandra有一个称为嵌入式Cassandra的东西,我们正在使用它。 - Derek Organ
啊,有趣 - 不确定Redis是否有类似的功能。对于我的集成测试,我们使用一个专门针对CI环境的Redis实例和特定的配置覆盖来指示测试应该针对该虚拟Redis实例运行。 - Adam
6个回答

20
我已经为Java实现了一个简单的Redis嵌入式运行程序:https://github.com/kstyrc/embedded-redis
目前,它使用redis 2.6.14作为*nix平台的版本,而在Windows平台上则使用https://github.com/MSOpenTech/redis。不过,你可以利用RedisServer类来运行自己的运行脚本。
我计划扩展这个实现以支持RedisConf(如bind、slaveof、port、dbfilename等)。完成后,我会将JAR上传到Clojars供Maven依赖使用。

当我在我的pom.xml中添加你在README.md中指示的依赖项片段时,它说找不到该依赖项。我还添加了存储库片段。你的代码现在托管在哪里? - Nishant Kelkar
我尝试过使用你们的嵌入式Redis项目,但无济于事。这里有一个与我的困扰相关的帖子:http://stackoverflow.com/questions/29059794 - balteo
@NishantKelkar 也许你应该刷新一下 Maven?这个构件在这里:https://clojars.org/repo/redis/embedded/embedded-redis/0.5/ - kstyrc
@kstyrc,你能否再次积极地开始处理这个JAR文件? - rajadilipkolli

11

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

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

需要注意的一件事是,集成测试不应替换单元测试。单元测试可能更受欢迎,因为它们可以涵盖更多情况,而集成测试只能用于检查应用程序的所有部分是否良好地运行在一起。我认为这就是为什么很多人选择第一种选项的原因。

这里有一个类似的问题关于mongodb。答案中有一个链接到该项目的答案,该项目可以用于第二个选项(控制mongodb进程)。如果您在项目页面上跟随一些相关链接,还有一些叫做nosql-unit的内容。我没用过它,但看起来它也适用于redis


3
您可以通过命令行在任意端口上启动Redis服务器:redis-server --port 7777。因此,为了进行集成测试,您可以在可用(或随机)端口上启动Redis,并确保Jedis配置为使用该端口。
这样,您就拥有了一个“新鲜”的Redis实例,您知道它不会与任何其他进程冲突,包括同时运行的其他测试运行。这是我能想到的类似于运行内存/嵌入式数据库进行集成测试的模拟。
要使用“预加载数据”预加载Redis,请使用--dbfilename <file>开关:redis-server --port 7777 --dbfilename test.rdb

2

尝试使用nosql-unit。它支持使用Java进行Redis单元测试。

我已经尝试过EmbeddedRedis,发现许多Jedis接口不受支持。因此,在使用一些高级Redis功能(如“pipeline”)时,使用EmbbededRedis不是一个好主意。

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

  1. redis.io下载Redis源代码到您的测试资源中
  2. 在$(your-redis-dir)/src中构建一个redis-server
  3. 使用ManagedRedis编写一个单元测试,这里有一个示例。注意,“REDIS_HOME”是您下载的Redis代码所在的目录,ManagedRedis将在${REDIS_HOME}/src中查找redis-server
  4. 运行您的单元测试。

1
如果你推荐一个库,最好展示一下它如何应用。请在你的回答中添加一些示例代码。 - Artjom B.

0
我处理这个问题的更好方法是创建一个Spring服务来处理RedisTemplate。之后,我只需使用@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团队的“官方”推荐。


0

正如@ksytrc在他的回答中提到的那样,我基本上使用了他的解决方案。它在这个项目中运行良好。你只需要添加embedded-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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接