Question

I've started using Redis in my project with the help of the Jedis library. All is working fine but now I have a problem that my functional tests requires Redis to be up which I want to avoid in my Continuous Integration. What is the best way to do this?

Était-ce utile?

La solution 2

Here are few options you have for functional/integration testing:

  1. Just start an instance of redis on you CI server. All tests will be responsible to do proper clean up after execution.
  2. Try somehow to control redis process, i.e. have some shell script or job on CI server to start/stop it before/after running tests. At least some of the burden of setup/cleanup is removed from tests, as for each independent build you will have independent redis setup.
  3. Control redis further by using some in-memory solution like the one you mention for cassandra(if it exists).

One thing to mention is that integration tests should not replace unit tests. Unit tests should probably be preferred and they can cover more cases whereas integration tests can be used just to check that all parts of application play nicely together. And i think this is the reason why a lot of people choose to go for option number one.

Here is a similar question about mongodb The answer has a link to the project which works for second option(controls mongodb process) If you follow some related links on the project page there's also something called nosql-unit. This one i think tries to cover option three. I didn't use it but looks like it has something for redis too.

Autres conseils

I've implemented a simple redis embedded runner for Java: https://github.com/kstyrc/embedded-redis

Currently, it uses redis 2.6.14 for*nix and https://github.com/MSOpenTech/redis for Windows. However you can utilize RedisServer class to run your own run script.

I plan to extend the implementation to support RedisConf (bind, slaveof, port, dbfilename, etc). After this, I'll upload jar to clojars for mvn deps.

You can start Redis server on an arbitrary port via the command line: redis-server --port 7777. So for the purposes of integration testing, you could start on Redis on an available (or random) port, making sure that Jedis is configured to use that port.

In this way, you've got a "fresh" instance of Redis that you know won't conflict with any other processes, including other test runs occurring at the same time. This is as close as I can think of to the analogue of running an in-memory/embedded database for integration testing.

For pre-loading Redis with "canned data," use the --dbfilename <file> switch: redis-server --port 7777 --dbfilename test.rdb.

try nosql-unit. It supports redis unit test with java.

I have tried EmbeddedRedis and found that many Jedis interfaces are not supported. Hence using EmbbededRedis is not a good idea, especially when you are using some advanced redis function like "pipeline".

I suggest using ManagedRedis for unit test:

  1. download a redis source code from redis.io into your test resource
  2. build a redis-server in the $(your-redis-dir)/src
  3. write a unit test with ManagedRedis, here is an example. Note that "REDIS_HOME" is the dir where your redis code downloaded, ManagedRedis will find redis-server in ${REDIS_HOME}/src
  4. run you unit test.

As @ksytrc mentioned in his answer I basically used his solution. It was working in this project.You just need to add embedded-redis dependency.

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

then in test class define the redisServer

RedisServer redisServer;

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

Also define application.yml with below credentials.

spring:
  redis:
    host: localhost
    port: 6379

The better way that I could handle this same problem was create a Spring service that handle the RedisTemplate. After that, I just use @MockBean to mock the service and abstract the lack of a Redis instance running during my tests.

Per example:

@Service
class RedisService {

    @Autowired
    private RedisTemplate<String, SomeClass> redisTemplate;

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

}

And in the integration test:

class IntegrationTest {

    @MockBean
    private RedisService redisService;

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


}

I'm skeptical to use some redis memory database solution, because I understand that the actual alternatives is not "officially" recommended by the Spring team.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top