如何在多个 SpringBootTests 之间重用 Testcontainers?
Posted
技术标签:
【中文标题】如何在多个 SpringBootTests 之间重用 Testcontainers?【英文标题】:How to reuse Testcontainers between multiple SpringBootTests? 【发布时间】:2020-10-07 01:42:38 【问题描述】:我正在使用带有 Spring Boot 的 TestContainers 为这样的存储库运行单元测试:
@Testcontainers
@ExtendWith(SpringExtension.class)
@ActiveProfiles("itest")
@SpringBootTest(classes = RouteTestingCheapRouteDetector.class)
@ContextConfiguration(initializers = AlwaysFailingRouteRepositoryShould.Initializer.class)
@TestExecutionListeners(listeners = DependencyInjectionTestExecutionListener.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Tag("docker")
@Tag("database")
class AlwaysFailingRouteRepositoryShould
@SuppressWarnings("rawtypes")
@Container
private static final PostgreSQLContainer database =
new PostgreSQLContainer("postgres:9.6")
.withDatabaseName("database")
.withUsername("postgres")
.withPassword("postgres");
但现在我有 14 个这样的测试,每次运行测试时都会启动一个新的 Postgres 实例。是否可以在所有测试中重用相同的实例? Singleton pattern 无济于事,因为每次测试都会启动一个新应用程序。
我也在.testcontainers.properties
和.withReuse(true)
中尝试过testcontainers.reuse.enable=true
,但这没有帮助。
【问题讨论】:
你试过 withReuse(true) 选项了吗? @P3trur0:是的。而testcontainers.reuse.enable=true
- 没有帮助。
尝试将容器实例作为@Bean
放入单独的@TestConfiguration
,然后在所有相关测试中导入此配置。
@NikolaiShevchenko:试过了,但 @ContextConfiguration(initializers
需要它,我无法让它在那里工作。
【参考方案1】:
如果您想拥有可重用的容器,则不能使用 JUnit Jupiter 注释 @Container
。此注解确保停止容器after each test。
您需要的是单例容器方法,并使用例如@BeforeAll
启动您的容器。即使您随后在多个测试中拥有.start()
,如果您选择在容器定义中同时使用.withReuse(true)
和主目录中的以下.testcontainers.properties
文件以实现可重用性,Testcontainers 也不会启动新容器:
testcontainers.reuse.enable=true
一个简单的例子可能如下所示:
@SpringBootTest
public class SomeIT
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll()
postgreSQLContainer.start();
@Test
public void test()
还有另一个集成测试:
@SpringBootTest
public class SecondIT
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll()
postgreSQLContainer.start();
@Test
public void secondTest()
目前有一个PR that adds documentation关于这个
我整理了一篇博文,详细解释了how to reuse containers with Testcontainers。
【讨论】:
非常感谢。然后我还需要用.withCommand("postgres -c max_connections=200")
增加我的max_connections
。如何控制可重用容器的生命周期?
我无法回答这个问题。也许值得看看介绍该功能的 PR:github.com/testcontainers/testcontainers-java/pull/1781
testcontainers.reuse.enable=true 记录在哪里?
是的,有多种方法可以配置此属性。查看 Testcontainers 文档的Configuration locations section。
你不能通过类路径设置testcontainers.reuse.enable
。 See this comment.【参考方案2】:
如果您决定继续使用singleton pattern,请注意“Database containers launched via JDBC URL scheme”中的警告。我花了几个小时才注意到,即使我使用的是singleton pattern,总是会创建一个额外的容器,映射到不同的端口。
总之,不要使用测试容器的 JDBC (host-less) URI,例如 jdbc:tc:postgresql:<image-tag>:///<databasename>
,如果你需要使用 singleton pattern。
【讨论】:
【参考方案3】:我不确定@Testcontainers
的工作原理,但我怀疑它可能对每个班级都有效。
只需按照Singleton pattern 中的说明将您的单例设为静态即可 并从你的signleton持有者的每个测试中获取它,不要在每个测试类中定义它。
【讨论】:
“单例模式没有帮助,因为每个测试都会启动一个新应用程序。”以上是关于如何在多个 SpringBootTests 之间重用 Testcontainers?的主要内容,如果未能解决你的问题,请参考以下文章