使用JUnit 5 TestFactory和大量dynamicTest(DynamicContainer/DynamicNode)时出现Java GC开销限制错误
在尝试使用maven surefire插件2.21.0创建和运行大量JUnit 5动态测试时,我面临以下问题 [错误]超出了GC开销限制 [错误]org.apache.maven.surefire.booter.SurefireBooterWorkException:分叉进程中出现错误 [错误]超出了GC开销限制 [错误]位于org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:673) [错误]位于org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:535) [错误]位于org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:280) [错误]位于org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245) [错误]位于org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1124) [错误]位于org.apache.maven.plugin.surefire.AbstractSurefireMojo.ExecuteAfterPremissionSchecked(AbstractSurefireMojo.java:954) [错误]位于org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:832) [错误]位于org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134) [错误]位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208) [错误]位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154) [错误]位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146) [错误]位于org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117) [错误]位于org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81) [错误]位于org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51) [错误]位于org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128) 下面是我的代码,它是一个db比较工具。基本上我所做的是,从两个数据库中传输数据并比较记录,如果两个记录中的任何一个存在差异,则测试将失败,因此将创建与数据库中记录数量相同的动态测试(~14M),非常大,不确定动态测试是否打算以这种规模使用。非常感谢您在这方面提供的任何帮助:)使用JUnit 5 TestFactory和大量dynamicTest(DynamicContainer/DynamicNode)时出现Java GC开销限制错误,junit,java-8,java-stream,maven-surefire-plugin,junit5,Junit,Java 8,Java Stream,Maven Surefire Plugin,Junit5,在尝试使用maven surefire插件2.21.0创建和运行大量JUnit 5动态测试时,我面临以下问题 [错误]超出了GC开销限制 [错误]org.apache.maven.surefire.booter.SurefireBooterWorkException:分叉进程中出现错误 [错误]超出了GC开销限制 [错误]位于org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:673) [
@TestFactory
Stream dynamicTestsWithContainers()引发SQLException{
return tableNameProvider()//数据库表列表~100
.map(tableName->dynamicContainer(tableName,dynamicodestream(tableName));
}
私有流dynamicodestream(字符串tableName){
试一试{
System.out.println(“测试”+表名);
Stream rows=sourceRepo.rows(tableName);
Stream batchRows=批次(行,10000);
可选tableInfo=sourceRepo.getTableSchema(tableName);
最终流dynamicodestream=batchRows
.flatMap(批处理->{
Map sourceRowsMap=buildRowMap(批处理,tableInfo.get());//包含10000个对象的HashMap
Map targetRowsMap=targetReporto.GetTargetBrows(sourceRowsMap,tableInfo.get());//包含10000个对象的HashMap
Set commonKeys=Set.intersection(sourceRowsMap.keySet(),targetRowsMap.keySet());
最终流dynamicTestStream=Streams.concat(
溪流(
dynamicTest(“所有源记录都应该存在于目标数据库中”,()->assertThat(targetRowsMap.keySet())
.as(“将“+sourceRepo.getServerName()+”与“+targetRepo.getServerName()进行比较”)
.hasSameElementsAs(sourceRowsMap.keySet())
),
公用钥匙
.stream()
.map(rowKey->dynamicTest(tableName+“行和#“+rowKey+”在目标数据库中应该是相同的”,
()->assertThat(targetRowMap.get(rowKey.getRowData())
.IseQualToComparingFieldByField递归(sourceRowsMap.get(rowKey.getRowData())
))
);
返回dynamicTestStream;
});
返回dynamicondesteam;
}捕获(例外e){
抛出新的RuntimeException(“在表上运行测试时出错”+tableName,e);
}
}
试试:
org.apache.maven.plugins
maven surefire插件
-XX:+UseConMarkSweepGC
在您的构建配置文件中允许并发垃圾收集。我们在这里讨论的是什么样的“规模”?换句话说,您的工厂生成了多少个动态测试?~1400万个测试,我正在尝试编写一个DB比较工具,为了比较每一行,我创建了一个动态测试。您能在不涉及maven/surefire的情况下运行测试吗?可能只是控制台启动器?从控制台启动器运行也会导致相同的错误。即使这是两年后的事,您可能会对进展感兴趣:
@TestFactory
Stream<DynamicNode> dynamicTestsWithContainers() throws SQLException {
return tableNameProvider()//List of db tables ~100
.map(tableName -> dynamicContainer(tableName, dynamicNodeStream(tableName)));
}
private Stream<DynamicNode> dynamicNodeStream(String tableName) {
try {
System.out.println("Testing " + tableName);
Stream<Row> rows = sourceRepo.rows(tableName);
Stream<List<Row>> batchRows = batch(rows, 10000);
Optional<TableSchema> tableInfo = sourceRepo.getTableSchema(tableName);
final Stream<DynamicNode> dynamicNodeStream = batchRows
.flatMap(batch -> {
Map<String, Row> sourceRowsMap = buildRowMap(batch, tableInfo.get());//HashMap with 10000 Objects
Map<String, Row> targetRowsMap = targetRepo.getTargetDBRows(sourceRowsMap, tableInfo.get());//HashMap with 10000 Objects
Set<String> commonKeys = Sets.intersection(sourceRowsMap.keySet(), targetRowsMap.keySet());
final Stream<DynamicTest> dynamicTestStream = Streams.concat(
Stream.of(
dynamicTest("All source records should be present in target DB", () -> assertThat(targetRowsMap.keySet())
.as("Comparing " + sourceRepo.getServerName() + " against " + targetRepo.getServerName())
.hasSameElementsAs(sourceRowsMap.keySet()))
),
commonKeys
.stream()
.map(rowKey -> dynamicTest(tableName + " Row with #" + rowKey + " should be same in target DB",
() -> assertThat(targetRowsMap.get(rowKey).getRowData())
.isEqualToComparingFieldByFieldRecursively(sourceRowsMap.get(rowKey).getRowData())
))
);
return dynamicTestStream;
});
return dynamicNodeStream;
} catch (Exception e) {
throw new RuntimeException("Error running tests on table " + tableName, e);
}
}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-XX:+UseConcMarkSweepGC</argLine>
</configuration>
</plugin>