2016-08-15 173 views
-2

我目前在學習Java。我進行了拋出異常的單元測試。我跑了單元測試但失敗了。任何承擔這一點?爲什麼Java在Java中的單元測試失敗?

這是我的代碼單元測試的

public Card(int rank, int suit) throws SuitOutOfRangeException, RankOutOfRangeException { 
    // TODO: Re-write this Constructor to throw exceptions 
    try { 
     if (suit > 4 || suit < 0) { 
      throw new SuitOutOfRangeException(); 
     } 
     this.suit = suit % 4; 
    } catch (SuitOutOfRangeException ex) { 
     System.out.println("Your input value for suit is out of the specified range"); 
    } 

    try { 
     if (rank > 12 || rank < 0) { 
      throw new RankOutOfRangeException(); 
     } 
     this.rank = rank % 13; 
    } catch (RankOutOfRangeException ex) { 

     System.out.println("Your input value for rank is out of the specified range"); 

    } 
} 

部分是如下所示:

@Test 
public void testConstructorShouldThrowRankOutOfRangeException() { 
    boolean expected = true; 
    boolean actual = false; 
    try { 
     Card c = new Card(100,1); 
     actual = false; 
    } catch (SuitOutOfRangeException ex) { 
     actual = false; 
    } catch (RankOutOfRangeException ex) { 
     actual = true; 
    } 
    assertEquals(expected,actual); 
} 

的解決方案是本

public Card(int rank, int suit) throws SuitOutOfRangeException, RankOutOfRangeException {   
    if (rank <0 || rank > 12) throw new RankOutOfRangeException(); 
    if (suit <0 || suit >3) throw new SuitOutOfRangeException(); 
    this.suit = suit % 4; 
    this.rank = rank % 13; 
} 
+2

你的單元測試會說清楚失敗的原因。請添加顯示您的測試失敗的錯誤消息。 – randominstanceOfLivingThing

+0

還要注意,這是一種可怕的測試方法,不會引發任何異常......只是調用構造函數,並且如果引發異常,測試將無法繼續。如果這些是檢查異常,我會讓它們不被檢查(你是否需要特定的異常?),如果你不能這樣做,只要讓測試方法聲明它可以拋出它們。 –

+0

此外,如果'rank'在範圍內[[0,12]'和'suit'在範圍內[[0,3]],爲什麼你使用'suit%4'和'rank%13'只是'西裝'和'等級'? –

回答

0

如果發現異常,則不能再捕捉它,除非它再次被拋入catch塊。

用JUnit你可以做這樣的事情

例如

@Rule public ExpectedException thrown = ExpectedException.none(); 

@Test 
public void throwsException() { 
    thrown.expect(NullPointerException.class); 
    thrown.expectMessage("happened"); 
    throw new NullPointerException("What happened?"); 
} 

http://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html

+0

但是你只給了那裏的例子。沒有解釋什麼類型的*拋出* ...我想這會相當混淆新手而不是幫助他們。 – GhostCat

1

讓我們給你的代碼的一些更普遍的反饋;也應該回答你不知道的「我該怎麼做」這個問題。

首先,有絕對毫無意義的拋出一個異常,並捕獲它在你的構造函數。減少到:

public Card(int rank, int suit) { // please note: no checked exceptions! 
    checkRank(rank); 
    checkSuit(suit); 
    this.suit = ... 

隨着檢查的方法,只是檢查並扔,像

private void checkSuit(int suit) { 
    if (suit < 0) throw new SuitOutOfRangeException("suit must not be negative: " + suit); 
    ... 

的一點是:你希望把你的代碼真的很小,很小的方法。這種方法只有一個責任(例如:檢查傳入服裝的有效範圍)。而且:當你拋出異常時,你會在後麪包含你需要的信息來理解你的失敗。

爲了測試這樣的事情,你去:

@Test(expected=SuitOutOfRangeException.class) 
public void testNegativeSuit() { 
    new Card(1, -1); 
} 

就是這樣。與printlns和布爾人沒有關係,沒有任何關係。所有這些都是浪費,不會增加任何有意義的東西;既不是你的生產邏輯;也不適用於您的測試用例。請注意:你也不需要奇怪的斷言。你期望拋出異常;沒有別的。所以這就是你要檢查的!

談論斷言;當你確實需要斷言時,瞭解斷言,如

Card underTest = new Card(1, 2); 
assertThat(underTest.getSuit(), is(2)); 

最後:考慮改變訴訟類型和等級從int。讓他們類。當然,你可以從一個int輸入構建一個Rank類;但也許還有其他選擇。事情是:編程是關於創建抽象。如果你不使用抽象...那麼你必須處理那些低級細節全部的時間。就像你的Card類必須知道int-ranks應該是什麼樣子一樣。如果你有一個等級和套裝類,那麼卡只能接受等級和套裝;並不會擔心int範圍!

+0

不錯的有用答案。 +1 –