有没有办法在每个测试类之后报告延迟线程? (junit的/行家)

时间:2017-09-28 10:59:48

标签: multithreading unit-testing junit4 maven-surefire-plugin

在编写糟糕的遗留代码库中,单元测试会调用触发永不停止的线程的代码。在大多数情况下,它没有效果,但在某些情况下,它会大大减慢构建速度,而在其他情况下,它会导致构建期间同一项目中的测试之间出现完全不明确的副作用:例如: test A启动线程,然后B在同一个JVM中运行并以一些未定义的方式中断(修复是让A停止该线程)。

是否有一些工具可以与junit一起使用,以便在每个测试结束时(或一个类中的一组测试),如果有任何线程在运行,它将无法通过测试?

这将使我们能够快速识别和修复所有现有案例,同时也阻止以这种方式编写新测试。

2 个答案:

答案 0 :(得分:0)

public class FailOnLingeringThreadsTestBase
{
    private static Set<Thread> threadsBefore;

    @BeforeClass
    public static void takePhoto()
    {
        threadsBefore = Collections.unmodifiableSet(Thread.getAllStackTraces().keySet());
    }

    @AfterClass
    public static void spotTheDiffs()
    {
        Set<Thread> threadsAfter = Thread.getAllStackTraces().keySet();
        if (threadsAfter.size() != threadsBefore.size())
        {
            threadsAfter.removeAll(threadsBefore);
            throw new IllegalStateException("Lingering threads in test: " + threadsAfter);
        }
    }
}

答案 1 :(得分:0)

显然,Maven / Surefire允许您使用配置挂钩监听器!这是通过将检查作为org.junit.runner.notification.RunListener的一部分实现来垂直集成检查的一种现实方法。

以下是我现在使用的内容:

public class FailOnLingeringThreadsRunListener extends org.junit.runner.notification.RunListener
{
    private Set<Thread> threadsBefore;

    @Override
    public synchronized void testRunStarted(Description description) throws Exception
    {
        threadsBefore = takePhoto();
        super.testRunStarted(description);
    }

    @Override
    public synchronized void testRunFinished(Result result) throws Exception
    {
        super.testRunFinished(result);

        Set<Thread> threadsAfter = spotTheDiffs(threadsBefore);

        // only complain on success, as failures may have caused cleanup code not to run...
        if (result.wasSuccessful())
        {
            if (!threadsAfter.isEmpty())
                throw new IllegalStateException("Lingering threads in test: " + threadsAfter);
        }
    }

    public static Set<Thread> takePhoto()
    {

        return Collections.unmodifiableSet(Thread.getAllStackTraces().keySet());
    }

    @AfterClass
    public static Set<Thread> spotTheDiffs(Set<Thread> threadsBefore)
    {
        Set<Thread> threadsAfter = Thread.getAllStackTraces().keySet();
        if (threadsAfter.size() != threadsBefore.size())
        {
            threadsAfter.removeAll(threadsBefore);
            return Collections.unmodifiableSet(threadsAfter);
        }

        return Collections.emptySet();
    }
}

以下是我在构建中启用它的方法:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <properties>
                        <property>
                            <name>listener</name>
                            <value>testutil.FailOnLingeringThreadsRunListener</value>
                        </property>
                    </properties>
                </configuration>
            </plugin>
...