如何以特定顺序应用JUnit规则?

8iwquhpp  于 2022-11-11  发布在  其他
关注(0)|答案(3)|浏览(110)

我们通过一个测试规则在每个测试中强制执行超时:

public abstract class BaseTestCase {
    @Rule
    public final Timeout timeout = new Timeout(60*1000);
}

那么我们的GUI测试显然必须在EDT上运行,所以他们也有一个测试规则:

public class TestSomeController extends BaseTestCase {
    @Rule
    public final RunOnEventDispatchThread runOnEventDispatchThread =
        new RunOnEventDispatchThread();

    @Test
    public void testStuff() { /* ... */ }
}

这两个规则都涉及到干扰测试运行的线程。Timeout创建一个新线程,然后在 N 毫秒后将其删除。RunOnEventDispatchThread在EDT上运行Runnable,然后等待任务完成。
在JUnit 4.10之前,这一直工作得很好,但是我们刚刚升级到JUnit 4.11,现在似乎测试规则的顺序发生了变化。
当前的JUnit似乎是按照“逻辑”顺序应用规则,因此它先应用Timeout,然后应用RunOnEventDispatchThread
这意味着RunOnEventDispatchThreadStatement“洋葱”的“外部”结束,因此它在EDT上运行任务,但是该任务现在“产生一个新线程来运行测试”--因为它产生了一个新线程,测试失败,因为Swing调用现在在错误的线程上被调用。
显然,JUnit4.10以另一种顺序运行测试规则。有什么方法可以影响这种情况吗?
注意,这类问题的现有答案都是通过使用RuleChain来解决的。就我所知,我们不能使用RuleChain,因为该类要求两个规则都在同一个类中,而我们的类则不是。

3duebb1j

3duebb1j1#

我对JUnit中的规则排序不是很熟悉,尤其是RuleChain类。所以我快速浏览了一下这个类的documentation。当在模板方法意义上使用时,示例代码片段似乎是您的解决方案。
我可以想象以下机制将起作用:

public abstract class BaseTestCase {

    @Rule
    public final RuleChain ruleChain = createRuleChain();

    private RuleChain createRuleChain() {
        return appendInnerRules(RuleChain.outerRule(createOuterRule()));
    }

    protected TestRule createOuterRule() {
        return new Timeout(60 * 1000);
    }

    protected RuleChain appendInnerRules(RuleChain ruleChain) {
        return ruleChain; // default behavior
    }

}

public final class TestSomeController extends BaseTestCase {

    protected RuleChain appendInnerRules(RuleChain ruleChain) {
        return ruleChain.around(new RunOnEventDispatchThread());
    }

    @Test
    public void testStuff() { /* ... */ }

}
gdrx4gfi

gdrx4gfi2#

official docs中,您可以执行以下操作:

@Rule
    public RuleChain chain= RuleChain
                           .outerRule(new LoggingRule("outer rule")
                           .around(new LoggingRule("middle rule")
                           .around(new LoggingRule("inner rule");

记录:

starting outer rule
 starting middle rule
 starting inner rule
 finished inner rule
 finished middle rule
 finished outer rule
iaqfqrcu

iaqfqrcu3#

因为junit 4.13可以使用元素顺序。

public class ThreeRules {
     @Rule(order = 0)
     public LoggingRule outer = new LoggingRule("outer rule");

     @Rule(order = 1)
     public LoggingRule middle = new LoggingRule("middle rule");

     @Rule(order = 2)
     public LoggingRule inner = new LoggingRule("inner rule");

     // ...
 }

相关问题