【问题标题】:How to connect to testcontainers redis correctly during spring boot integration test?spring boot集成测试期间如何正确连接testcontainers redis?
【发布时间】:2022-06-14 14:11:29
【问题描述】:

我正在 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);
    }
}

当我在调试模式下运行它并点击断点时,我注意到控制台中的端口 redis.getMappedPort(6379) 不等于 stringRedisTemplate.connectionFactory.clientmyService.stringRedisTemplate.connectionFactory.client

System.setProperty是否覆盖了属性并在这种情况下生效? 如何在 Spring Boot 集成测试中使用 testcontainers?

【问题讨论】:

  • 使用 TestContainers 和 Container 注释,您可以让测试容器管理生命周期,但在这里您有自己的专用启动和停止方法。这可能是问题之一。

标签: java spring-boot testcontainers


【解决方案1】:

我建议使用与playtika 稍有不同的容器,后者构建在测试容器之上。

您需要做的是在您的pom.xml 中包含spring-cloud-starter-bootstrap(作为测试依赖项就足够了)。

然后在您的测试中 application.yaml|properties 使用以下内容:

spring:
  redis:
    port: ${embedded.redis.port}
    password: ${embedded.redis.password}
    host: ${embedded.redis.host}
    ssl: false

【讨论】:

    【解决方案2】:

    您可以使用getFirstMappedPort() 而不是redis.getMappedPort(6379),因为 testcontainer 使用随机端口。 6379是宿主机端口,但是redis容器的端口是随机分配的,避免冲突。更多细节可以在另一个线程中找到:https://stackoverflow.com/a/50869731

    【讨论】:

      猜你喜欢
      • 2019-05-30
      • 2019-04-22
      • 2017-10-29
      • 2020-07-28
      • 1970-01-01
      • 2018-10-31
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多