junit5_一个在自己的线程中运行测试的JUnit规则

junit5

junit5

有时,能够在单独的线程中运行JUnit测试会很有帮助。 特别是在编写与封装的ThreadLocal或类似对象交互的集成测试时,这可能会派上用场。 单独的线程将隐式确保每次测试运行都未初始化threadlocal的与线程相关的引用。 这篇文章介绍了提供此类功能的JUnit规则,并说明了如何使用它。

首先,请看以下示例。 它描述了一个导致testB间歇性故障的testB 。 原因是结果取决于副作用1导致的所有测试的执行顺序。 更准确地说, Display.getDefault()原则上返回延迟实例化的单例,而Display.getCurrent()是此单例的简单访问器。 结果,如果testBtestA 2之后运行,则testB失败。

public class FooTest {

  @Test
  public void testA() {
    Display actual = Display.getDefault();

    assertThat( actual ).isNotNull();
  }

  @Test
  public void testB() {
    Display actual = Display.getCurrent();

    assertThat( actual ).isNull();
  }
}

为了避免某些幕后魔术,使人难以理解代码,我们可以确保在实际测试执行之前就放置了现有的显示器3

@Before
  public void setUp() {
    if( Display.getCurrent() != null ) {
      Display.getCurrent().dispose();
    }
  }

不幸的是,这种方法不能在运行PDE测试的集成测试套件中使用。 PDE运行时将创建一个Display实例,其生存期跨越所有测试运行。 因此,显示处置将不是一个选择,并且testBtestB在PDE测试套件执行中失败4

此时,请务必记住, Display单例已绑定到其创建线程(准ThreadLocal ) 5 。 因此,如果在自己的线程中执行,则testB应该运行可靠。

但是,线程处理通常最好情况下比较麻烦,并且会造成很多混乱,从而降低了测试方法的可读性。 这给了我创建一个TestRule实现的想法,该实现封装了线程处理并保持测试代码干净:

public class FooTest {

  @Rule
  public RunInThreadRule runInThread = new RunInThreadRule();

  @Test
  public void testA() {
    Display actual = Display.getDefault();

    assertThat( actual ).isNotNull();
  }

  @Test
  @RunInThread
  public 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

  1. 请注意,默认情况下,JUnit以确定性但不可预测的顺序对测试方法进行排序
  2. 还考虑testA可能在另一个测试用例中并且仅在运行大型套件时才会出现问题的可能性
  3. 再说一次,我也不喜欢这种做法,因此,对于更复杂的解决方案,您可以查看一下“简化SWT测试设置的JUnit规则”一文。
  4. 同时,您可能已经认识到,简单的示例测试用例不是很有用,但是我希望足以说明动机。
  5. 这使这样的线程成为SWT中的用户界面线程。 SWT实现了通常称为单元线程的单线程UI模型

翻译自: https://www.javacodegeeks.com/2014/07/a-junit-rule-to-run-a-test-in-its-own-thread.html

junit5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值