Junit4: @Parameters 方法在 @ClassRule 初始化之前执行。 可能是这样吗?

创建于 2013-05-02  ·  9评论  ·  资料来源: junit-team/junit4

我有以下问题(使用_junit 4.11_):

    <strong i="6">@ClassRule</strong>
    public static TemporaryFolder tmp = new TemporaryFolder();
    ...
    <strong i="7">@Parameters</strong>
    public static Collection<Object[]> data() throws Exception {
        return java.util.Arrays.asList(new Object[][] {
            {0, tmp.getRoot().getPath()}
        });
    }

这会导致初始化错误

java.lang.IllegalStateException: the temporary folder has not yet been created
    at org.junit.rules.TemporaryFolder.getRoot(TemporaryFolder.java:127)

所以似乎_@Parameters_方法是在 _ClassRule_ 初始化阶段之前执行的,这使得上面的场景有点复杂。

最有用的评论

当前解决方法:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

它可以工作,但需要手动清理......

所有9条评论

当前解决方法:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

它可以工作,但需要手动清理......

+1

想一想,我想实现这一点的一个好方法是为此引入一个注释:

<strong i="7">@Parameters</strong>
<strong i="8">@AfterClassRules</strong>
public Object[][] generateParameters() {
    // do stuff
}

这将确保两种变体仍然可用,并且现有代码不会被破坏。 如果维护人员可以接受这种设计,我将开始为此提出拉取请求。

我正在写一条附加评论,因为我不确定评论的更新是否会触发通知。

我之前评论中提出的设计会被维护者接受吗? 如果是这样,我将开始处理拉取请求。

这里有一个相当困难的架构问题:JUnit 向 Eclipse 之类的运行器承诺,它可以在运行任何测试之前枚举有多少测试,但还希望最大限度地减少在此规划阶段消耗的任何资源。 所以我们真的很想知道在我们之前会有多少参数,例如,创建任何临时文件夹,或者执行 ClassRules 中出现的更激烈的事情,比如启动服务器。

也许我最喜欢的答案是在 Theories 中启用@DataPoints 之类的东西:可以有以@ParameterSet为前缀的静态字段或静态方法,它们结合在一起构成完整的参数集。 所以你的例子是:

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet public static Object[] first = new Object[] { 0 };
@ParameterSet public static Object[] second() {
return new Object[] { tmp.getRoot().getPath(); }
}

这里的重点是我们可以在不实际执行的情况下计算方法“秒”。

你怎么看?

嗯,我想现在我想起来了,这个问题实际上更多的是我的测试代码中的气味。 我正在连接到远程服务并根据其配置方式运行测试。 相反,我可能应该在我的测试中修复预期的配置。

这是我最初遇到问题的测试: CryptoAppExecReturnCodeTest.java

@dsaff我会考虑一下您的建议。 最初的印象是:将对拆分为单独的数组需要特别注意元素的位置(容易出错)。 所以我最终可能会用一些虚拟的东西填充_first_(只是保持元素的数量); 并在_second_中-我想将pair元素彼此相邻:

{ 0, tmp...getPath() },
{ 1, ... }

除了测试次数之外,跑步者还需要什么? (例如 - 也许是测试名称?)

@javornikolov ,我刚刚意识到我误读了您的初始帖子,因此我的回复可能令人困惑。 我将您的测试视为使用一个参数构造的测试类的两个不同实例; 现在我再次阅读它,它实际上是一个由两个参数构造的测试类的实例。 然后调整我的建议,建议的代码是:

<strong i="7">@ClassRule</strong> public static TemporaryFolder tmp = new TemporaryFolder();
<strong i="8">@ParameterSet</strong> public static Object[] only() {
return new Object[] { 0, tmp.getRoot().getPath(); }
}

我希望这能让我的意图更清楚; 对不起我最初的困惑。

(通过一些旧的错误)

也许我们应该将此问题重命名为“在理论中启用@DataPoints 之类的东西”?

(通过一些旧的错误)

也许我们应该将此问题重命名为“在理论中启用@DataPoints 之类的东西”?

我会说问题是能够在参数化测试的参数列表中使用Rule资源。 @dsaff提出的@ParameterSet方法对我来说似乎是可行的(假设评估以解决原始问题的顺序进行)。
但是,如果“类似@DataPoints 的东西”足够清晰,并且没有在不涵盖原始场景的方向上出现分歧的风险:对我来说还可以。
我更喜欢参数化测试而不是理论(使用数据点)的原因是后者的结果不会为每组参数独立报告,并且第一次失败会中止后续参数的执行。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

sabi0 picture sabi0  ·  13评论

terorontti picture terorontti  ·  14评论

kcooney picture kcooney  ·  108评论

sbrannen picture sbrannen  ·  22评论

keltik85 picture keltik85  ·  3评论