Java JUnit@规则生命周期与@Before的交互

Java JUnit@规则生命周期与@Before的交互,java,junit,lifecycle,rules,Java,Junit,Lifecycle,Rules,我有一些JUnit测试使用临时文件夹@Rule。他们使用@Before方法中的临时文件夹执行一些设置: @Rule public TemporaryFolder folder = new TemporaryFolder(); @Before public void init() { folder.newFile("my-file.txt"); } @Test public void myTest() { ... } 大多数情况下,这种方法都非常有效。但是,在使用SpringJUnit4

我有一些JUnit测试使用
临时文件夹
@Rule
。他们使用
@Before
方法中的
临时文件夹
执行一些设置:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Before
public void init() {
  folder.newFile("my-file.txt");
}

@Test
public void myTest() { ... }
大多数情况下,这种方法都非常有效。但是,在使用
SpringJUnit4ClassRunner
时,我发现在某些情况下,在应用
TemporaryFolder
实例中的
语句之前会调用
init()
方法。因此,当在
init()
中使用
文件夹时,临时文件夹位置是未设置的(即:
null
),并且我的文件最终位于工作目录中,而不是
/tmp

因此,在某些情况下,在执行
方法之前先执行
,但是,我无法建立一个明确的模式。我偶尔会在自己的一些规则实现中看到类似的问题


是否有任何方法可以确保在任何设置方法之前应用我的规则语句

在JUnit 4.10中,BlockJUnit4ClassRunner(SpringJUnit4ClassRunner的超类)似乎注意构造语句链,以使规则在任何@before方法之前运行。来自JUnit 4.10:

protected Statement methodBlock(FrameworkMethod method) {
    // ...
    Statement statement= methodInvoker(method, test);
    statement= possiblyExpectingExceptions(method, test, statement);
    statement= withPotentialTimeout(method, test, statement);
    statement= withBefores(method, test, statement);
    statement= withAfters(method, test, statement);
    statement= withRules(method, test, statement);
    return statement;
}
JUnit 4.7似乎以不同的顺序将语句链缝合在一起:

Statement statement= methodInvoker(method, test);
statement= possiblyExpectingExceptions(method, test, statement);
statement= withPotentialTimeout(method, test, statement);
statement= withRules(method, test, statement);
statement= withBefores(method, test, statement);
statement= withAfters(method, test, statement);
return statement;

spring-test-3.0.5的父POM似乎表明它依赖于JUnit4.7。我想知道让它使用更新的JUnit是否会有所帮助?

出于它的价值,我使用了以下方法作为快速解决方案:

@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder() {
    @Override
    protected void before() throws Throwable {
        if (getRoot() == null) {
            super.before();
        }
    }

    @Override
    public File newFile(String fileName) throws IOException {
        try {
            before();
        }
        catch (Throwable t) {
            throw new RuntimeException(t.getMessage(), t);
        }

        return super.newFile(fileName);
    }

    @Override
    public File newFolder(String folderName) {
        try {
            before();
        }
        catch (Throwable t) {
            throw new RuntimeException(t.getMessage(), t);
        }

        return super.newFolder(folderName);
    }
};

这可确保正确初始化
临时文件夹
,而不管是在规则之前还是之后运行
@Before
方法。

Good find@pholser。我使用的是JUnit 4.8.x,它似乎以与4.10相同的顺序构造链。但是,methodBlock()在SpringJUnit4ClassRunner中被重写,并设置了与JUnit4.7类似的不同顺序。