1. Overview

Spring Data Redis provides an easy way to integrate with Redis instances.

However, in some cases, it's more convenient to use an embedded server than to create an environment with a real server.

Therefore, we'll learn how to set up and use the Embedded Redis Server.

2. Dependencies

Let's begin by adding the necessary dependencies:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>embedded-redis</artifactId>
  <version>0.7.2</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

The spring-boot-starter-test dependency contains everything we need to run integration tests.

Additionally, the embedded-redis contains the embedded server that we'll use.

3. Setup

After adding the dependencies, we should define the connection settings between the Redis server and our application.

Let's begin by creating a class that will hold our properties:

@Configuration
public class RedisProperties {
    private int redisPort;
    private String redisHost;

    public RedisProperties(
      @Value("${spring.redis.port}") int redisPort, 
      @Value("${spring.redis.host}") String redisHost) {
        this.redisPort = redisPort;
        this.redisHost = redisHost;
    }

    // getters
}

Next, we should create a configuration class that defines the connection and uses our properties:

@Configuration
@EnableRedisRepositories
public class RedisConfiguration {

    @Bean
    public LettuceConnectionFactory redisConnectionFactory(
      RedisProperties redisProperties) {
        return new LettuceConnectionFactory(
          redisProperties.getRedisHost(), 
          redisProperties.getRedisPort());
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        return template;
    }
}

The configuration is quite simple. Additionally, it allows us to run the embedded server on a different port.

Check out our Introduction to Spring Data Redis article to learn more about the Redis with Spring Boot.

4. Embedded Redis Server

Now, we'll configure the embedded server and use it in one of our tests.

Firstly, let's create an application.properties file in the test resource directory (src/test/resources):

spring.redis.host=localhost
spring.redis.port=6370

After that, we'll create a @TestConfiguration-annotated class:

@TestConfiguration
public class TestRedisConfiguration {

    private RedisServer redisServer;

    public TestRedisConfiguration(RedisProperties redisProperties) {
        this.redisServer = new RedisServer(redisProperties.getRedisPort());
    }

    @PostConstruct
    public void postConstruct() {
        redisServer.start();
    }

    @PreDestroy
    public void preDestroy() {
        redisServer.stop();
    }
}

The server will start once the context is up. It'll start on our machine on the port that we've defined in our properties. For instance, we can now run the test without stopping the actual Redis server.

Ideally, we'd like to start it on the random available port but embedded Redis doesn't have this feature yet. What we could do right now is to get the random port via the ServerSocket API.

Additionally, the server will stop once the context is destroyed.

The server can also be provided with our own executable:

this.redisServer = new RedisServer("/path/redis", redisProperties.getRedisPort());

Furthermore, the executable can be defined per operating system:

RedisExecProvider customProvider = RedisExecProvider.defaultProvider()
  .override(OS.UNIX, "/path/unix/redis")
  .override(OS.Windows, Architecture.x86_64, "/path/windows/redis")
  .override(OS.MAC_OS_X, Architecture.x86_64, "/path/macosx/redis")
  
this.redisServer = new RedisServer(customProvider, redisProperties.getRedisPort());

Finally, let's create a test that'll use our TestRedisConfiguration class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestRedisConfiguration.class)
public class UserRepositoryIntegrationTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void shouldSaveUser_toRedis() {
        UUID id = UUID.randomUUID();
        User user = new User(id, "name");

        User saved = userRepository.save(user);

        assertNotNull(saved);
    }
}

The user has been saved to our embedded Redis server.

Additionally, we had to manually add TestRedisConfiguration to SpringBootTest. As we said earlier, the server has started before the test and stopped after.

5. Conclusion

The Embedded Redis Server is the perfect tool to replace the actual server in the test environment. We've seen how to configure it and how to use it in our test.

As always, the code for examples is available over on GitHub.