在 Jedis 库的帮助下,我开始在我的项目中使用 Redis。一切正常,但现在我有一个问题,我的功能测试需要 Redis 启动,我想在我的持续集成中避免这种情况。做这个的最好方式是什么?
6 回答
我已经为 Java 实现了一个简单的 redis 嵌入式运行器: https ://github.com/kstyrc/embedded-redis
目前,它使用 redis 2.6.14 for *nix 和https://github.com/MSOpenTech/redis for Windows。但是,您可以利用 RedisServer 类来运行您自己的运行脚本。
我计划扩展实现以支持 RedisConf(绑定、slaveof、端口、dbfilename 等)。在此之后,我会将 jar 上传到 clojars 用于 mvn deps。
以下是功能/集成测试的几个选项:
- 只需在 CI 服务器上启动一个 redis 实例。所有测试都将负责在执行后进行适当的清理。
- 尝试以某种方式控制 redis 进程,即在运行测试之前/之后在 CI 服务器上有一些 shell 脚本或作业来启动/停止它。至少从测试中消除了一些设置/清理的负担,因为对于每个独立的构建,您将拥有独立的 redis 设置。
- 通过使用一些内存中的解决方案来进一步控制 redis,例如您为 cassandra 提到的解决方案(如果存在)。
需要提到的一件事是集成测试不应该取代单元测试。单元测试可能应该是首选,它们可以涵盖更多情况,而集成测试可以用于检查应用程序的所有部分是否可以很好地协同工作。我认为这就是为什么很多人选择选择第一的原因。
这是关于 mongodb的类似问题答案有一个链接到适用于第二个选项的项目(控制 mongodb 进程)如果您按照项目页面上的一些相关链接进行操作,那么还有一个叫做nosql-unit的东西。我认为这个试图涵盖选项三。我没有使用它,但看起来它也适用于redis。
您可以通过命令行在任意端口上启动 Redis 服务器:redis-server --port 7777
. 因此,出于集成测试的目的,您可以在可用(或随机)端口上启动 Redis,确保 Jedis 配置为使用该端口。
这样,您就有了一个“新鲜”的 Redis 实例,您知道它不会与任何其他进程发生冲突,包括同时发生的其他测试运行。这与我能想到的运行内存/嵌入式数据库进行集成测试的类比非常接近。
要使用“预设数据”预加载 Redis,请使用以下--dbfilename <file>
开关:redis-server --port 7777 --dbfilename test.rdb
.
尝试nosql-unit。它支持用java进行redis单元测试。
试过EmbeddedRedis,发现很多Jedis接口都不支持。因此,使用 EmbbededRedis 不是一个好主意,尤其是当您使用一些高级 redis 功能(如“管道”)时。
我建议使用 ManagedRedis 进行单元测试:
正如@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
我可以处理同样问题的更好方法是创建一个 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 团队“官方”推荐的。