我们有 Spring Boot 集成测试,并定期编写新的测试。 我注意到数据库连接不断堆积:我运行的测试越多,我的 PostgreSQL 实例的连接峰值就越高。
在运行所有测试时,Spring Boot 请求的连接数超过 300 个,并且构建开始失败(我们的
max_connection
设置为 300)。
经过一些研究,我了解到运行测试后连接不会被释放,因为 Spring Boot 测试:如果上下文没有显式销毁,连接不会关闭。
我觉得这很奇怪,但尝试使用
@DirtiesContext
来证明一点,在我们所有的测试类上,它确实在某种意义上解决了问题,避免了峰值(一次不超过 30 个连接,不会堆积到300 像以前一样),但由于此注释强制在每个测试类之前重新创建上下文,因此构建速度变慢了很多,而且我发现每次都需要重新创建 Spring 上下文以确保连接正确关闭,这并不是很令人满意。
数据源是一个
HikariDataSource
,使用配置类进行配置。
我发现的另一个解决方法是更改 Hikari 的最大池大小。我将其设置为低于默认值 10(我不确定为每个测试类保留 10 个连接是否有用)。当我运行所有测试时,此更改有效地降低了连接总数,但它们仍在堆积(只是更低!)
我想我错过了一些东西,如何确保每个测试类后连接都关闭?一定有比
@DirtiesContext
更好的方法,我就是找不到。感谢您的帮助。
事实证明,几乎每个测试类都重新创建了上下文,因为我在测试中广泛使用了
@MockBean
注释。由于它会影响 Spring 上下文,因此不同测试类中的每个 @MockBean
/No MockBean 组合都算作不同的上下文,即:
在这种情况下,由于bean配置不同,将为每个类创建一个新的Spring上下文,从而导致与数据源的连接数量不断增加。
为了(部分)解决这个问题,我在测试类的 beans 组合中寻找模式,并创建了一个名为
TestMockBeans
的新类。
其唯一目的是声明尽可能多的 MockBean 和/或 SpyBean 以便在类似的测试配置中重用。我使用
TestMockBeans
扩展相应的测试类,然后,因为它们共享相似的设置,Spring 将它们的上下文识别为相似的,并且不会为每个测试类重新创建一个新的上下文。
正如您所猜测的,并非我在整个 Spring boot 应用程序中的所有测试都对 Mockbeans 具有相同的需求(或缺少 Mockbeans),因此这只是部分解决方案,但我希望它能帮助遇到相同问题的人减轻问题。
限制上下文刷新的解决方法也是很有价值的建议。 但我必须在测试之间的 Spring 重新初始化期间限制连接或使它们关闭。
下面链接的建议对我有用,只是限制
spring.datasource.hikari.maximum-pool-size=2