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?
3
Answers
I prepared 2 templates in Java and Kotlin, which are working for me (servlet not webflux), for your reference.
Here is the Kotlin version:
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:You can use
getFirstMappedPort()
rather thanredis.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