在编写糟糕的遗留代码库中,单元测试会调用触发永不停止的线程的代码。在大多数情况下,它没有效果,但在某些情况下,它会大大减慢构建速度,而在其他情况下,它会导致构建期间同一项目中的测试之间出现完全不明确的副作用:例如: test A启动线程,然后B在同一个JVM中运行并以一些未定义的方式中断(修复是让A停止该线程)。
是否有一些工具可以与junit一起使用,以便在每个测试结束时(或一个类中的一组测试),如果有任何线程在运行,它将无法通过测试?
这将使我们能够快速识别和修复所有现有案例,同时也阻止以这种方式编写新测试。
答案 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>
...