junit测试线程
有时,能够在单独的线程中运行JUnit测试会很有帮助。 特别是在编写与封装的ThreadLocal
或类似对象进行交互的集成测试时,这可能会派上用场。 单独的线程将隐式确保每次测试运行都未初始化threadlocal的与线程相关的引用。 这篇文章介绍了提供此类功能的JUnit 规则 ,并说明了如何使用它。
首先,请看以下示例。 它描述了一个导致testB
间歇性故障的testB
。 原因是结果取决于副作用1导致的所有测试的执行顺序。 更精确地说, Display.getDefault()
原则上返回延迟实例化的单例,而Display.getCurrent()
是此单例的简单访问器。 结果,如果testB
在testA
2之后运行,则它失败。
public class FooTest {@Testpublic void testA() {Display actual = Display.getDefault();assertThat( actual ).isNotNull();}@Testpublic void testB() {Display actual = Display.getCurrent();assertThat( actual ).isNull();}
}
为了避免出现幕后魔术,这种魔术会使代码难以理解,我们可以确保在实际测试执行之前就放置了现有的显示器3 。
@Beforepublic void setUp() {if( Display.getCurrent() != null ) {Display.getCurrent().dispose();}}
不幸的是,这种方法不能在运行PDE测试的集成测试套件中使用。 PDE运行时将创建一个Display
实例,其生存期跨越所有测试运行。 因此,显示处置将不是一个选择,并且testB
在PDE测试套件执行期间testB
会失败4 。
此时,请务必记住, Display
单例已绑定到其创建线程(准ThreadLocal
) 5 。 因此,如果在自己的线程中执行,则testB
应该运行可靠。
但是,线程处理通常充其量是比较麻烦的,并且会造成很多混乱,从而降低了测试方法的可读性。 这给了我创建一个TestRule实现的想法,该实现封装了线程处理并保持测试代码干净:
public class FooTest {@Rulepublic RunInThreadRule runInThread = new RunInThreadRule();@Testpublic void testA() {Display actual = Display.getDefault();assertThat( actual ).isNotNull();}@Test@RunInThreadpublic void testB() {Display actual = Display.getCurrent();assertThat( actual ).isNull();}
}
RunInThreadRule
类允许在其自己的线程中运行单个测试方法。 它负责守护程序线程的创建,测试执行,等待线程终止以及将测试结果转发到主线程。 为了将测试标记为在单独的线程中运行,测试方法必须使用@RunInThread
注释,如上所示。
这样, testB
现在就独立于测试的执行顺序,并且成功可靠。 但是请注意不要过度使用RunInThreadRule
。 尽管@RunInThread
批注表示测试在单独的线程中运行,但未解释原因。 这可能很容易混淆这种测试的真实范围。 因此,我通常仅将此作为万不得已的解决方案。 例如,当第三方库依赖于无法通过API功能清除或重置的封装ThreadLocal
,这可能是合理的。
对于那些想了解RunInThreadRule
实现的人,我创建了一个GitHub gist:
https://gist.github.com/fappel/65982e5ea7a6b2fde5a3
对于现实世界的使用,您还可以查看托管在以下位置的Gonsole项目的PgmResourceBundlePDETest
实现:
https://github.com/rherrmann/gonsole 。
- 请注意,默认情况下,JUnit以确定性但不可预测的顺序对测试方法进行排序
- 还考虑
testA
可能在另一个测试用例中并且仅在运行大型套件时才会出现问题的可能性 - 再说一次,我也不喜欢这种做法,因此,对于更复杂的解决方案,您可以查看一下“简化SWT测试设置的JUnit规则”一文。
- 同时,您可能已经认识到,简单的示例测试用例不是很有用,但我希望足以说明动机。
- 这使这样的线程成为SWT中的用户界面线程。 SWT实现通常称为单元线程的单线程UI模型
翻译自: https://www.javacodegeeks.com/2014/07/a-junit-rule-to-run-a-test-in-its-own-thread.html
junit测试线程