2011-10-12 48 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方法之前或規則之後運行。