并行 JUnit 测试不执行关闭挂钩

Posted

技术标签:

【中文标题】并行 JUnit 测试不执行关闭挂钩【英文标题】:Parallel JUnit tests don't execute shutdown hook 【发布时间】:2015-12-27 13:14:37 【问题描述】:

我正在使用 Maven 在并行类中运行多个 JUnit 测试。我有清理所有 JUnit 测试运行后需要执行的任务。为了处理这种清理,我在一些测试中添加了一个关闭挂钩。当我 并行运行时,关闭挂钩正确执行,但是当我并行运行时,我看不到关闭挂钩的输出(参见示例)。有什么我做错了吗?在 JUnit 测试中并行执行时,JVM 是否使用System.exit 退出?

根据 Surfire 文档文档,并行线程在同一个进程中执行,所以我希望 Runtime.getRuntime 是同一个进程,即使它在不同的测试和线程之间被调用。 Maven Surfire Plugin - Fork Options and Parallel Test Execution

使用并行选项要记住的重要一点是: 并发发生在同一个 JVM 进程中。这是有效的 内存和执行时间方面,但你可能更容易受到攻击 朝向比赛条件或其他意想不到且难以重现的情况 行为。

这是我的单元测试中的一个示例:

@Test
public void test()

    Runtime.getRuntime().addShutdownHook(new Thread()
    
        @Override
        public void run()
        
            System.out.println("Test clean up triggered");
        
    );

这是我的 pom 的相关部分:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18.1</version>
    <configuration>
        <parallel>classes</parallel>
        <threadCount>10</threadCount>
    </configuration>
</plugin>

已编辑: 当我在 @BeforeClass 方法中添加关闭挂钩时,问题得到解决。当我在@Test 方法中添加它时,我遇到了问题。我希望能够随时添加钩子。

【问题讨论】:

【参考方案1】:

实际上调用了您的关闭挂钩,我认为问题来自与 maven 的关闭挂钩相关的 system.out.println 调用。

直接用Eclipse测试,我有输出:

Test clean up triggered

并尝试稍微不同的测试版本:

    @Test
    public void test()
    
        System.out.println("Testing");
        Runtime.getRuntime().addShutdownHook(new Thread()
        
            @Override
            public void run()
            
                try 
                                Files.createFile(Paths.get("test1"));
                             catch (IOException e) 
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            
            
        );

        assertTrue(true);   
    

我可以在我的director 的根目录中看到调用mvn clean test 后创建的文件“test1”

测试:

openjdk 版本“1.8.0_121” Junit 4.12 Maven 3.3.9 Maven surefire-plugin 2.17

【讨论】:

我的问题的关键是在 Maven 中并行运行测试,并在 @BeforeClass 中设置了关闭挂钩。当我复制问题时,它是一个更大项目的一部分。我刚刚建立了一个快速 2 测试项目,但问题没有重现。我不知道这是否仍然重现,因为问题是一段时间前我无法确定是否执行了错误修复,或者我的大型项目中是否存在其他问题。 @JeredM 上面的示例仅用于演示目的。在@BeforeClass 方法中初始化关闭挂钩确实更明智。现在,使用上面列出的设置,我尝试了各种组合,我遇到的唯一失败是由于无序测试(试图在声明之前删除钩子,这是预期的错误)。出于好奇,您是否还有用于解决此故障的设置? 我没有那个设置了:(

以上是关于并行 JUnit 测试不执行关闭挂钩的主要内容,如果未能解决你的问题,请参考以下文章

Junit 并行执行测试

如何在Gradle中为单个测试类并行执行JUnit测试

带有 @Suite 注释的 Junit5 测试套件不使用 mvn test 命令执行测试

JUnit 和 Surefire 并行测试 - ForkCount 和 ThreadCount

Myeclipse7.0 中Junit 单元测试,怎么不可以单个方法执行

如何关闭多项目构建的并行执行测试?