'How to connect to testcontainers redis correctly during spring boot integration test?
I am writing test for my service in spring boot
@Component
public class MyService {
@Autowired
StringRedisTemplate stringRedisTemplate;
// a number of other @Autowired dependencies
public User getUser(String uuid) {
var key = String.format("user:%s", uuid);
var cache = stringRedisTemplate.opsForValue().get(key);
if (cache == null) {
// return user from database
} else {
// return user from deserialized cache
}
}
}
@Testcontainers
@SpringBootTest
class MyServiceTest {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
MyService myService;
@Container
public static GenericContainer<?> redis =
new GenericContainer<>("redis:5.0.14-alpine3.15").withExposedPorts(6379);
@BeforeClass
public static void startContainer() {
redis.start();
var redisUrl = String.format("redis://%s:%s", redis.getHost(), redis.getMappedPort(6379));
System.setProperty("spring.redis.url", redisUrl);
}
@AfterClass
public static void stopContainer() {
redis.stop();
}
@Test
void getUser_returnCachedUser() {
// breakpoint here
stringRedisTemplate.opsForValue().set("user:some-uuid", "{\"uuid\":\"some-uuid\",\"name\":\"cache\"}");
var user = myService.getUser("some-uuid");
assertEquals("cache", user.name);
}
}
When I ran this in debug mode and hit breakpoint, I noticed port redis.getMappedPort(6379) in console was not equal to stringRedisTemplate.connectionFactory.client or myService.stringRedisTemplate.connectionFactory.client.
Did System.setProperty overwrite properties and take effect in this case?
How can I use testcontainers in spring boot integration test?
Solution 1:[1]
I'd suggest to use slightly different container from playtika which is built on top of testcontainers.
What you need to do is to include spring-cloud-starter-bootstrap in your pom.xml (it's enough as a test dependency).
and then in your test application.yaml|properties use following:
spring:
redis:
port: ${embedded.redis.port}
password: ${embedded.redis.password}
host: ${embedded.redis.host}
ssl: false
Solution 2:[2]
You can use getFirstMappedPort() rather than redis.getMappedPort(6379) because testcontainer uses random ports. 6379 is host machine port, but the redis container's port is randomly assigned to avoid conflicts. More details could be found in another thread: https://stackoverflow.com/a/50869731
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | bilak |
| Solution 2 | enesify |
