2016-12-15 77 views
0

我遇到了一個問題JUnit 4.12我無法解釋什麼時候測試應該拋出特定異常的代碼中的方法。 我使用@Test註釋(預期= MyException.class)。 MyException僅從Exception派生。JUnit測試與預期的異常並不像預期的那樣

由於一個編程錯誤失蹤「扔」條款)這個不引發異常。由於測試用例設置包括使用jmockit 1.29的模擬類,隨後在該方法中拋出了NullPointerException。

示例類shwoing基本客艙佈局:

package l00tr.test; 

public class MyException extends Exception { 
    private static final long serialVersionUID = 1L; 
    public MyException(String msg) { 
     super(msg); 
    } 
} 

package l00tr.test; 

import java.util.Map; 
import java.util.Set; 

public class MyClass { 

    private Set<String> testSet; 
    private Map<String, String> testMap; 
    private boolean condition; 

    private MyClass() { 
     this.testSet = null; 
     this.testMap = null; 
     this.condition = false; 
    } 
    private MyClass(Set<String> testSet, Map<String, String> testMap, 
      boolean condition) { 
     this.testSet = testSet; 
     this.testMap = testMap; 
     this.condition = condition; 
    } 
    public void method() throws MyException { 
     if (testSet.size() < 2) { 
      throw new MyException("test set"); 
     } 
     if (!condition) { 
      // FORGOTTEN: throw 
      new MyException("test"); 
     } 
     System.out.print("set size: " + testSet.size()); 
     System.out.print("some more stuff succeeding"); 
     System.out.print("map size: " + testMap.size()); // NullPointerException 
    } 
    public static final class Builder { 
     private Set<String> testSet; 
     private Map<String, String> testMap; 
     private boolean condition; 
     private Builder() { 
      this.testSet = null; 
      this.testMap = null; 
      this.condition = false; 
     } 
     public static Builder newBuilder() { 
      return new Builder(); 
     } 
     public Builder testSet(Set<String> testSet) { 
      this.testSet = testSet; 
      return this; 
     } 
     public Builder testMap(Map<String, String> testMap) { 
      this.testMap = testMap; 
      return this; 
     } 
     public Builder condition(boolean condition) { 
      this.condition = condition; 
      return this; 
     } 
     public MyClass build() { 
      return new MyClass(testSet, testMap, condition); 
     } 
    } 
} 

所以我希望測試失敗。但它確實成功了。刪除「(expected = ...)」 Test註釋的一部分導致測試失敗,NullPointerException如預期的那樣。

package l00tr.test; 

import java.util.Set; 
import org.junit.Test; 
import mockit.Expectations; 
import mockit.Mocked; 

public class MyClassTests { 
    @Mocked 
    private Set<String> testSet; 

    @Test(expected = MyException.class) 
    public void testMethod() throws MyException { 
     new Expectations() { 
      { 
       testSet.size(); 
       result = 3; 
      } 
     }; 
     MyClass mc = MyClass.Builder.newBuilder().condition(false) 
       .testSet(testSet).build(); 
     mc.method(); 
    } 
} 

雅科科幫助發現這一點,否則我會錯誤地認爲一切都很好。我也檢查了junit 4.12的公開問題,但沒有找到匹配的問題。

爲什麼測試成功?有任何想法嗎?

更新:

我提高了例子來說明我的代碼的相關細節。不幸的是,上面粘貼代碼沒有像預期的那樣,即顯示錯誤:

java.lang.Exception: Unexpected exception, expected<l00tr.test.MyException> but was<java.lang.NullPointerException> 

我的具體開發環境的設置可以起到一定的作用,所以這裏有一些細節:

  • gradle這個3.2.1活性守護程序
  • 的junit 4.12
  • jmockit 1.29
  • 蝕Neon.1a推出(4.6.1)
  • Java版本「1.8.0_112」 64位
  • 的Windows 10
+1

讓我看看你的全部測試。你是否從TestCase延伸? http://stackoverflow.com/a/5550830/912829 – ACV

+0

@ACV謝謝你,我也找到了答案。我不是(明知)擴展TestCase。上面的代碼被簡化以適應這裏,但我會擴展它以更好地顯示我的代碼結構。 – l00tr

+0

如果使用Junit 4註釋,則不需要擴展測試用例。但是,我不能在Junit 4中重現這個問題,因此總結要在堆棧溢出上發佈的代碼 - 缺少某些內容。使用Junit4進行基於註釋的異常檢查常見的「誤報」問題是,您希望發生的異常滿足您的註釋,而不是您真正想要測試的異常。來自JUnit 4的 –

回答

0

了有益的意見後,我發現,這個問題可能收窄至「‘假陽性’與基於註解的異常問題與Junit4"檢查:

再次檢查完整堆棧跟蹤和代碼,包括一個抽象超之後,我發現一個try/catch轉換任何異常登錄後MyException。所以從工具和代碼的角度來看,一切都按預期工作。

+0

好交易,很高興你知道了! –