为什么这在Java中进行单元测试失败?

时间:2016-08-15 16:27:25

标签: java unit-testing

我目前正在学习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 个答案:

答案 0 :(得分:1)

让我们对您的代码提供一些更一般的反馈;也应该回答你的某些不清楚的问题&#34;我该怎么做&#34;问题

首先,抛出异常并在构造函数中捕获它有绝对没有意义。减少到:

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);
}

那就是它。印刷品和布尔都没有这种情况。所有这些都是浪费,没有任何有意义的东西;既不符合你的生产逻辑;也不是你的测试用例。请注意:您也不需要进行奇怪的断言。你希望抛出异常;没有别的。这就是你要检查的内容!

谈论断言;当你需要断言时,了解断言,如

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

最后:考虑改变套装的类型和排名。让他们真正的类。当然,您可以从int输入构建Rank类;但也许,还有其他选择。事情是:编程是关于创建抽象。如果你不使用抽象......那么你必须处理那些低级细节所有时间。就像你的Card类必须知道有效的int-rank应该是什么样子。如果你有Rank和Suit课程,那么Card只能获得Rank和Suit;并且不必担心int范围!

答案 1 :(得分:0)

如果你遇到异常,除非它再次被抛出catch区块,否则它不会被再次捕获。

使用Junit你可以做这样的事情

e.g。

@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