2011-08-08 116 views
26

如果在測試用例中出現測試失敗或錯誤,JUnit是否有方法在@After註釋方法內檢測?在@After方法中檢測Junit測試失敗或錯誤

一個醜陋的解決辦法是這樣的:在測試代碼

boolean withoutFailure = false; 

@Test 
void test() { 
    ... 
    asserts... 
    withoutFailure = true; 
} 

@After 
public void tearDown() { 
    if(!withoutFailuere) { 
     this.dontReuseTestenvironmentForNextTest(); 
    } 
} 

這是醜陋的,因爲一個需要照顧的「基礎設施」(withoutFailure標誌)。

我希望有一些東西可以在@After方法中獲得測試狀態!?

+0

是不是你的'@ Before'方法以確保環境設置正確的每一個測試護理? –

+0

@Vineet Reynolds:是和否:我正在使用Selemium2/Webdriver進行測試,我想重新使用驅動程序。但是如果之前的測試沒有任何錯誤,我只想重用。 – Ralph

+0

好的,我目前的問題。我試圖避免國旗。希望看到其他答案。如果我遇到一個合理的解決方案,我會發布我的。 –

回答

8

如果你足夠幸運能夠使用JUnit 4.9或更高版本,TestWatcher將完全符合你的要求。

分享和享受!

+5

由於此帖後面的TestWatchman已被棄用,TestWatcher是新的類。 – jconlin

+0

鏈接現已停止。 –

+3

這不適用於JUnit 4.12和Arquillian 1.1.10,因爲TestWatcher會在執行'@ After'方法後得到失敗的通知。 –

2

我想你要做的是在JUnit內核中添加RunListener。然後,您可以覆蓋testFailure方法,將您的withoutFailure標誌設置在一個位置,以便您可以在您的@After帶註釋的方法中檢查它。

另請參閱:this blog post,以便在使用早期版本的JUnit時討論此方法的一些問題。

1

我擴展了dsaff的答案,以解決TestRule無法在測試方法執行和後續方法執行之間執行某些代碼的問題。因此,使用簡單的MethodRule,不能使用此規則提供在@After帶註釋的方法中使用的成功標誌。

我的想法是黑客!無論如何,這是使用TestRule(延伸TestWatcher)。 A TestRule將獲得有關測試失敗或成功的知識。然後,我的TestRule將掃描該類中所有用我的新AfterHack批註註釋的方法,並使用成功標誌調用該方法。


AfterHack註釋

import static java.lang.annotation.ElementType.METHOD; 
import static java.lang.annotation.RetentionPolicy.RUNTIME;  
import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 

@Retention(RUNTIME) 
@Target(METHOD) 
public @interface AfterHack {} 

AfterHackRule

import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.ArrayList; 
import java.util.List; 

import org.junit.rules.TestWatcher; 
import org.junit.runner.Description; 

public class AfterHackRule extends TestWatcher { 

    private Object testClassInstance; 
    public AfterHackRule(final Object testClassInstance) { 
     this.testClassInstance = testClassInstance; 
    } 

    protected void succeeded(Description description) { 
     invokeAfterHackMethods(true); 
    } 

    protected void failed(Throwable e, Description description) { 
     invokeAfterHackMethods(false); 
    } 

    public void invokeAfterHackMethods(boolean successFlag) { 
     for (Method afterHackMethod : 
        this.getAfterHackMethods(this.testClassInstance.getClass())) { 
      try { 
       afterHackMethod.invoke(this.testClassInstance, successFlag); 
      } catch (IllegalAccessException | IllegalArgumentException 
        | InvocationTargetException e) { 
       throw new RuntimeException("error while invoking afterHackMethod " 
          + afterHackMethod); 
      } 
     } 
    } 

    private List<Method> getAfterHackMethods(Class<?> testClass) { 
     List<Method> results = new ArrayList<>();    
     for (Method method : testClass.getMethods()) { 
      if (method.isAnnotationPresent(AfterHack.class)) { 
       results.add(method); 
      } 
     } 
     return results; 
    } 
} 

用法:

public class DemoTest { 

    @Rule 
    public AfterHackRule afterHackRule = new AfterHackRule(this); 

    @AfterHack 
    public void after(boolean success) { 
     System.out.println("afterHack:" + success); 
    } 

    @Test 
    public void demofails() { 
     Assert.fail(); 
    } 

    @Test 
    public void demoSucceeds() {} 
} 

順便說一句:

  • 1)希望有在Junit5
  • 更好的解決方案
  • 2)更好的方法是在所有使用規則TestWatcher代替@Before和@After方法的(即我讀dsaff的答案的方式)

@see

1

我不知道任何簡單的或優雅的方式來檢測的方法@After JUnit測試失敗。

如果可以使用TestRule而不是@After方法,則可以使用兩個鏈接的TestRules,使用TestWatcher作爲內部規則。

例子:

package org.example; 

    import static org.junit.Assert.fail; 

    import org.junit.Rule; 
    import org.junit.Test; 
    import org.junit.rules.ExternalResource; 
    import org.junit.rules.RuleChain; 
    import org.junit.rules.TestRule; 
    import org.junit.rules.TestWatcher; 
    import org.junit.runner.Description; 

    public class ExampleTest { 

     private String name = ""; 
     private boolean failed; 

     @Rule 
     public TestRule afterWithFailedInformation = RuleChain 
     .outerRule(new ExternalResource(){ 
      @Override 
      protected void after() { 
      System.out.println("Test "+name+" "+(failed?"failed":"finished")+"."); 
      }  
     }) 
     .around(new TestWatcher(){ 
      @Override 
      protected void finished(Description description) { 
      name = description.getDisplayName(); 
      } 
      @Override 
      protected void failed(Throwable e, Description description) { 
      failed = true; 
      }  
     }) 
     ; 

     @Test 
     public void testSomething(){ 
     fail(); 
     } 

     @Test 
     public void testSomethingElse(){ 
     } 

    } 
+0

但是,當我能夠使用TestRule而不是@After時,那麼我可以使用TestRule並且不需要'RuleChain' - 或者我錯過了什麼? – Ralph

+0

RuleChain ...部分通過將兩個規則「連接」在一起(TestWatcher和ExternalResource)構造一個新的TestRule。您可以獨立指定這些規則,但是可能會發生after()方法在failed()之前執行的情況。 System.out.println()部分是您將放入相應的@After方法中的部分。 – Gustave

+0

我不明白的是:爲什麼我不應該簡單地使用它在測試之後運行的'TestWatcher',並且有''succeeded'方法和''failed''方法? – Ralph