针对 class 类型 Java 的 Junit 测试无效

Junit testing void against class type Java

我在测试 void 函数时遇到问题。

如果你看下面的代码,那么当我想测试它时,我最终得到一个 (Deck, void) 并且无法测试它(参见 DeckTest)

编辑:我如何测试一副纸牌是否已创建,即 public void createDeck()

public class Deck {

public Deck() {
    this.cards = new ArrayList<Card>();
}

...

public void createDeck() {
    for (Suit suit : Suit.values()) {
        for (Rank rank : Rank.values()) {
            this.cards.add(new Card(rank, suit));
        }
    }
}

...

}

现在进行 junit 测试

public class DeckTest extends TestCase {

Deck deck = new Deck();

@Test
public void testCreateDeck() throws Exception {
    assertEquals(deck, deck.createDeck()); <--- I have (Deck, void)
}

...

}

如何使用我的 "public void createDeck" 在 Junit 中测试是否已创建套牌?

Se link 完整代码

https://gist.github.com/kazyka/7a56617337d21706ec5e

assertEquals (deck, deck.createDeck()) 行正在将 Deck 对象与 void(由 createDeck() 方法返回)进行比较,因此断言将失败。

为了便于测试,您可以考虑 re-designing 沿着具有:

  • a Deck class,以及
  • 一个DeckFactory

如果你这样做,你将能够测试 DeckFactory 确实构建了有效的 Deck 实例。 class 正在测试中,您可以在任何需要新 Deck.

的地方使用它

这里有一些粗略的样板,可以让您了解我所说的要点:

public class Cards {

    public static void main(String[] args) {
        final Deck deck = new DeckFactory().newInstance();

        //... do stuff with the deck...
    }
}

class Deck {}

class DeckFactory {
    public Deck newInstance() {
        return new Deck();
    }
}

class DeckFactoryTest {
    private DeckFactory deckFactory;

    @Before
    public void setUp() {
        deckFactory = new DeckFactory();
    }

    @Test
    public void has52Cards() {
        //...
    }

    @Test
    public void has13Spades() {
        //...
    }
}

想想你想测试哪些方面。

你想测试...

  • ...是否有 52 张卡片进入了您的列表?
  • ...如果您的列表中有四种不同的花色?
  • ...如果您的列表中有 13 张数字和人头牌?

理想情况下,您应该测试所有三个方面,但真正的问题在于您的方法编写方式。您无法孤立地测试其中任何一项。

请注意,此函数 void 实际上很重要 很少 void 方法只是意味着您的对象的状态已经改变,要测试它,您需要测试状态。不过,我稍后会讲到。

首先,我们需要对您的逻辑进行一些重组。

让我们首先编写一个方法,使我们能够为给定花色生成所有 13 张牌。这应该足够简单了。

密切关注此方法的可见性。这是我们要公开测试的方法,但不是本质上开放给世界使用的方法.因此,我们使用 package-private 可见性。如果您有 Guava,请考虑使用 @VisibleForTesting 作为一个友好的提醒,告诉您为什么它不是 publicprivate

List<Card> generateCardsForSuit(final Suit suit) {
    final List<Card> result = new ArrayList<>();
    for(Rank rank : Rank.values()) {
        result.add(new Card(rank, suit);
    }
    return result;
}

这可以单独测试。给定一个有效的 Suit,它应该能够:

  • 生成 13 张牌
  • 包含所有十三个等级
  • 有一套连续花色

有趣的是,我们已经测试了我们在此特定功能中关心的 3 件事中的 2 件事。现在,让我们把它放回 void 方法中。

public void createDeck() {
    for (Suit suit : Suit.values()) {
        this.cards.addAll(generateCardsForSuit(suit));
    }
}

我们将不得不公开一个 getter 来检索 cards 列表,因此我们实际上可以根据它的一个实例来验证事情。再次注意该方法的可见性。

List<Card> getCards() {
    return cards;
}

既然我们已经轻松地测试了给定花色中的牌数,测试了它们的均匀性,并测试了它们的点数是否正确,那么我们需要做的就是测试我们生成的结果是否正确此方法的一部分,使用 getCards() 作为查看对象状态的一种方式。

这也让我们可以加入王牌,这将在牌组中引入 54 张牌,而不是仅仅 52 张,这将是一个独立于为牌组创建所有等级和花色的功能。