弹簧集成测试消耗大量内存,在GradleWorkerMain中使用大量重复线程备选案文1.配置渐变测试任务备选案文2.向测试资源添加 spring.properties结论奖金

2022-09-03 01:05:18

我有一个有点复杂的Spring Boot应用程序,有大量的测试。

在运行测试时,它似乎正在积累很多线程,其中一个线程有多个实例,并且被称为 ,我将其追溯到此依赖项SimplePauseDetectorThread_0

|    |    |    \--- io.micrometer:micrometer-core:1.1.1
|    |    |         +--- org.latencyutils:LatencyUtils:2.0.3

这似乎发生在Spring Boot 2.0.6以及2.1.1上。

典型的测试可能如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@ActiveProfiles(profiles = {"test"})
public class MyTest {
[...]

我的执行器配置如下所示:

management.endpoints.enabled-by-default=false
management.endpoint.prometheus.enabled=true
management.endpoints.web.base-path=/
management.endpoints.web.exposure.include=prometheus
management.endpoints.web.path-mapping.prometheus=prometheus
spring.metrics.prometheus.enabled=true

查看随附的屏幕截图

enter image description here


答案 1

来自Pivotal的Snicoll在GitHub上帮助我,暗示它可能与Spring Boot测试框架中的上下文缓存相关联。

如果您有大量使用spring集成的测试和数量较多的上下文配置(您只显示了一个类),那么将为每个配置创建一个上下文,我可以看到该场景中线程的数量增加。

然后,他向我指出了相关文档,其中指出:

您可以通过设置名为 spring.test.context.cache.maxSize 的 JVM 系统属性,从命令行或构建脚本配置最大大小。作为替代方法,您可以使用 SpringProperties API 以编程方式设置相同的属性。

并指出:org.springframework.core.SpringProperties

Reads a {@code spring.properties} file from the root of the Spring library classpath

这给我们留下了两种设置方式。maxSize

备选案文1.配置渐变测试任务

向 gradle 任务添加一个属性,该属性将配置 :testGradleWorkerMainbuild.gradle

test {
    jvmArgs "-Dspring.test.context.cache.maxSize=1"
}

如果您有许多子项目,则可能需要使用此选项。

请参阅下面的“奖金”,了解将设置应用于所有子项目的方法。

备选案文2.向测试资源添加 spring.properties

您可以在 中编写设置,如下所示:my-service/src/test/resources/spring.properties

spring.test.context.cache.maxSize=1

结论

现在,我的测试运行良好,内存消耗更少,线程更少。

奖金

这也解决了 Gradle 5+ 的工作线程默认具有 512MB 最大堆(而不是系统 RAM 的 25%)的问题 - 子项目测试套件不再吹走所有可用的 RAM,如果我在项目配置中没有添加具有较大堆的自定义 jvmargs,这将导致工作线程 OOM。我现在可以在 gradle worker 中使用“vanilla”堆大小运行。testjava

如果确实想要调整可用于Gradle测试的RAM,请在根目录中执行类似操作:build.gradle

allprojects { project ->
    project.plugins.withId('java') {
        test {
            maxHeapSize = "1536M"
            // If you don't want to use spring.properties (or add other JVM args)
            jvmArgs "-Dspring.test.context.cache.maxSize=1"
        }
    }
    project.plugins.withId('java-library') {
        test {
            maxHeapSize = "1536M"
            // If you don't want to use spring.properties (or add other JVM args)
            jvmArgs "-Dspring.test.context.cache.maxSize=1"
        }
    }
}

答案 2

推荐