运行 @SpringBootTest 类 时连接未关闭并堆积
Connections are not closed and piling up when running @SpringBootTest classes
我们有 Spring 引导集成测试,并会定期编写新的测试。
我注意到数据库连接一直在堆积:我 运行 的测试越多,我的 PostgreSQL 实例的连接峰值就越高。
当 运行 进行所有测试时,Spring 引导请求了超过 300 个连接,并且开始构建失败(我们的 max_connection
设置为300).
经过一些研究,我了解到在测试 运行 之后连接不会被释放,因为 Spring 启动测试:如果上下文没有被明确破坏,连接就不会被释放已关闭。
我觉得很奇怪,但尝试使用 @DirtiesContext
来证明一点,在我们所有的测试 classes 中,它确实在某种意义上解决了问题,它避免了峰值(没有一次超过 30 个连接,而不是像以前那样堆积到 300 个)但是由于这个注释在每次测试之前强制重新创建上下文 class,构建速度变慢了很多,我发现需要重新创建一个 Spring 上下文每次只是为了确保连接正确关闭。
数据源是 HikariDataSource
,使用配置 class 进行配置。
我发现的另一个解决方法是更改 Hikari 的最大池大小。我将它设置为低于默认值 10 的值(我不确定为每个测试保留 10 个连接是否有用 class)。当我 运行 所有测试但它们仍在堆积时(仅更低!)
,此更改有效地降低了连接总数
我想我遗漏了一些东西,如何确保每次测试后连接都关闭 class?一定有比 @DirtiesContext
更好的方法,我就是找不到。感谢您的帮助。
事实证明,几乎每次测试都会重新创建上下文 class,因为我在测试中广泛使用了 @MockBean
注释。由于它会影响 Spring 上下文,因此不同测试 classes 中的每个 @MockBean
/No MockBean 组合都算作不同的上下文,即:
- 测试class1:bean MyService 是一个 MockBean,MyOtherService 不是
- 测试class2:bean MyService是一个MockBean,MyOtherService也是一个MockBean
- 测试class3:none这两个bean是一个MockBean
在这种情况下,将为每个 class 创建一个新的 Spring 上下文,因为 bean 配置不同,导致与数据源的连接数增加。
为了(部分)解决这个问题,我在我的测试 classes 的 beans 组合中寻找模式并创建了一个新的 class 我称之为 TestMockBeans
.
它的唯一目的是声明尽可能多的 MockBeans and/or SpyBeans,以便在类似的测试配置中重复使用。我用 TestMockBeans
扩展相应的测试 classes,然后,因为它们共享这个相似的设置,Spring 将它们的上下文标识为相似并且不会为每个测试重新创建一个新的 class.
如您所料,并非我在整个 Spring 启动应用程序中的所有测试都对 Mockbeans 有相同的需求(或缺少 Mockbeans),因此这只是部分解决方案,但我希望它能对某人有所帮助遇到同样的问题来缓解它。
我们有 Spring 引导集成测试,并会定期编写新的测试。 我注意到数据库连接一直在堆积:我 运行 的测试越多,我的 PostgreSQL 实例的连接峰值就越高。
当 运行 进行所有测试时,Spring 引导请求了超过 300 个连接,并且开始构建失败(我们的 max_connection
设置为300).
经过一些研究,我了解到在测试 运行 之后连接不会被释放,因为 Spring 启动测试:如果上下文没有被明确破坏,连接就不会被释放已关闭。
我觉得很奇怪,但尝试使用 @DirtiesContext
来证明一点,在我们所有的测试 classes 中,它确实在某种意义上解决了问题,它避免了峰值(没有一次超过 30 个连接,而不是像以前那样堆积到 300 个)但是由于这个注释在每次测试之前强制重新创建上下文 class,构建速度变慢了很多,我发现需要重新创建一个 Spring 上下文每次只是为了确保连接正确关闭。
数据源是 HikariDataSource
,使用配置 class 进行配置。
我发现的另一个解决方法是更改 Hikari 的最大池大小。我将它设置为低于默认值 10 的值(我不确定为每个测试保留 10 个连接是否有用 class)。当我 运行 所有测试但它们仍在堆积时(仅更低!)
,此更改有效地降低了连接总数我想我遗漏了一些东西,如何确保每次测试后连接都关闭 class?一定有比 @DirtiesContext
更好的方法,我就是找不到。感谢您的帮助。
事实证明,几乎每次测试都会重新创建上下文 class,因为我在测试中广泛使用了 @MockBean
注释。由于它会影响 Spring 上下文,因此不同测试 classes 中的每个 @MockBean
/No MockBean 组合都算作不同的上下文,即:
- 测试class1:bean MyService 是一个 MockBean,MyOtherService 不是
- 测试class2:bean MyService是一个MockBean,MyOtherService也是一个MockBean
- 测试class3:none这两个bean是一个MockBean
在这种情况下,将为每个 class 创建一个新的 Spring 上下文,因为 bean 配置不同,导致与数据源的连接数增加。
为了(部分)解决这个问题,我在我的测试 classes 的 beans 组合中寻找模式并创建了一个新的 class 我称之为 TestMockBeans
.
它的唯一目的是声明尽可能多的 MockBeans and/or SpyBeans,以便在类似的测试配置中重复使用。我用 TestMockBeans
扩展相应的测试 classes,然后,因为它们共享这个相似的设置,Spring 将它们的上下文标识为相似并且不会为每个测试重新创建一个新的 class.
如您所料,并非我在整个 Spring 启动应用程序中的所有测试都对 Mockbeans 有相同的需求(或缺少 Mockbeans),因此这只是部分解决方案,但我希望它能对某人有所帮助遇到同样的问题来缓解它。