英文:
Spring boot - Test classes not letting go of database connections after finishing
问题
我有一个Spring Boot应用程序,我需要测试其中的所有内容。我遇到了这个问题。
当我启动我的测试(例如从**Gitlab**流水线启动时),测试从一开始就运行得很快。但是测试完成得越多,速度就越慢。加载另一个测试类的Spring应用程序上下文变得越来越慢。我还发现,在测试过程中,**数据库连接保持活动状态**,应用程序在**所有测试都完成之后**才释放它们,即使**大多数类在很长时间前就已经完成**。是否有人在以前遇到过这个问题,并找到了解决方法?
我在测试中使用的注释:
// Service test class example
@ExtendWith(SpringExtension.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import({SomeService.class})
@Sql("classpath:testdata/some_test_data.sql")
public class SomeServiceTest {
// Controller test class example
@ComponentScan(basePackages = {"some.package.with.tests"})
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@SpringBootTest
@Transactional
@Sql("classpath:testdata/some_test_data.sql")
public class SomeControllerTest {
英文:
I have a Spring Boot application where I need to test everything. I have run into this problem.
When I launch my tests (for example from Gitlab pipeline), tests are running fast from the beginning. But the more tests are done, the slower it gets. Loading Spring application context for another test class gets slower and slower. I have also found out, that during the tests, database connections stays active and application lets go of them after all of the tests are finished, even though most of the classes have already finished a long time ago. Have anyone run into this problem before and found solution for it please?
My annotations used in tests:
// Service test class example
@ExtendWith(SpringExtension.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import({SomeService.class})
@Sql("classpath:testdata/some_test_data.sql")
public class SomeServiceTest {
// Controller test class example
@ComponentScan(basePackages = {"some.package.with.tests"})
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@SpringBootTest
@Transactional
@Sql("classpath:testdata/some_test_data.sql")
public class SomeControllerTest {
答案1
得分: 1
我已经通过两个步骤解决了这个问题:
步骤1:DirtiesContext 注解 - 这会在特定类的测试完成后释放数据库连接,因此如果我设置 maximum-pool-size: 5
,它现在将只使用这 5 个连接。
用法:
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
步骤2:增加测试内存 - 我还必须增加单元测试的内存,以免出现 OutOfMemoryException
。MAVEN_OPTS
对我无效,所以我不得不在 pom.xml 中使用并配置此插件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>-Xmx2048m</argLine>
</configuration>
</plugin>
之后,我的测试流水线时间大大缩短。之前大约需要 20-30 分钟,现在只需要 8 分钟。
非常感谢 @AndyWilkinson 的好建议!
编辑!!!
在此之后,我的测试在 Sonar 上报告的覆盖率为 0%。经过一些时间的搜索,我还为此找到了解决方案:
步骤3:定义属性 sonar.surefire.argLine
<properties>
...
<sonar.surefire.argLine>-Xmx2048m</sonar.surefire.argLine>
</properties>
步骤4:重写插件的 <argLine>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>@{argLine} ${sonar.surefire.argLine}</argLine>
</configuration>
</plugin>
问题在于,jacoco 插件需要访问 surefire 的 argLine,但在您手动添加它后,不再可能。这就是我不得不添加 @{argLine}
的原因,jacoco 使用它。${sonar.surefire.argLine}
仅用于更好的代码外观,这样我就可以将 -Xmx2048m
参数与其他定义的属性一起使用。
英文:
I was able to fix this problem with two steps:
Step 1: DirtiesContext annotation - This released DB connections after finishing tests from a specific class, so if I set maximum-pool-size: 5
it would now use only those 5 connections.
Usage:
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
Step 2: Increasing memory for tests - I also had to increase memory for Unit tests so I wouldn't get OutOfMemoryException
. MAVEN_OPTS
didn't work for me, so I had to use and configure plugin for this in pom.xml.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>-Xmx2048m</argLine>
</configuration>
</plugin>
After this, my test pipeline time was much faster. From about 20-30 minutes before, it now took 8 minutes.
Thank you very much @AndyWilkinson for your good advices
EDIT!!!!
After this, my tests got coverage 0% reported on Sonar. After spending some time searching, I have found solution also for this:
Step 3: Define property sonar.surefire.argLine
<properties>
...
<sonar.surefire.argLine>-Xmx2048m</sonar.surefire.argLine>
</properties>
Step 4: Rewrite the plugin <argLine>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>@{argLine} ${sonar.surefire.argLine}</argLine>
</configuration>
</plugin>
The problem here was, that jacoco plugin needs to have access to surefire's argLine, but after you add it manually, it is no longer possible. That's why I had to add @{argLine}
, which jacoco uses. ${sonar.surefire.argLine}
is just for better code appearance, so I could have -Xmx2048m
argument with other defined properties.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论