2011-10-12 58 views
11

我有一些JUnit测试使用TemporaryFolder@Rule。他们使用TemporaryFolder@Before方法来执行一些设置:JUnit @Rule与@Before的生命周期交互

@Rule 
public TemporaryFolder folder = new TemporaryFolder(); 

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

@Test 
public void myTest() { ... } 

这其中大部分作品完美的时间。但是,在使用SpringJUnit4ClassRunner时,我发现在某些情况下,在应用我的TemporaryFolder实例内的Statement之前将调用init()方法。因此,在init()内使用folder时,临时文件夹位置未设置(例如:null),而我的文件最终在工作目录中,而不是在/tmp中。

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

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

回答

11

在JUnit 4.10中,BlockJUnit4ClassRunner(SpringJUnit4ClassRunner的超类)似乎注意构造Statement链,使得规则在任何@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; 

弹簧试验3.0.5母公司POM似乎表明,它依赖于JUnit的4.7。我想知道是否让它使用更新的JUnit会有所帮助?

+1

不错,找到@pholser。我使用的是JUnit 4.8.x,它似乎按照4.10的顺序构建链。然而,methodBlock()在SpringJUnit4ClassRunner中被覆盖,并设置了与JUnit 4.7相似的顺序。 – teabot

0

对于它的价值,我用下面作为一个快速的解决方法:

@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); 
    } 
}; 

这确保了TemporaryFolder正确初始化,无论是否@Before方法之前或规则之后运行。