2016-08-15 174 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 –