测试一副牌

时间:2016-12-07 15:40:19

标签: java testing mockito

尝试学习如何用Java进行测试并认为我已经很久了,因为感觉就像我试验和错误越多,我理解的就越少。我无法通过填充模拟卡来弄清楚如何测试甲板?我想能够测试甲板上的第一张牌实际上是在牌组被洗牌之前的两张牌,或者可能比较它为测试所做的一整套牌,但现在它完全静止了。有没有得到任何关于用卡片测试甲板的技巧的人?


Card.java

package model;

public class Card {

    public enum Value {
        Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Knight, Queen, King, Ace
    }

    public enum Suite {
        Hearts, Spades, Diamonds, Clubs
    }

    private Value value;
    private Suite suite;

    public Card(Value value, Suite suite) {
        if(value == null || suite == null){
            throw new IllegalArgumentException("Argument can't be null");
        }

        this.value = value;
        this.suite = suite;
    }

    public Object getValue() {
        return this.value;
    }

    public Object getSuite() {
        return this.suite;
    }

    public String toString(){
        return value + " of " + suite;
    }
}


Deck.java

package model;
import java.util.ArrayList;

public class Deck {

    private ArrayList<Card> cards = new ArrayList<Card>();  
    private CardFactory CF = new CardFactory();

    public Deck(){
        init();
    }

    public void init() {        
        for (int i=0; i<13; i++){    
            for (int j=0; j<4; j++){
                //card = cardFactory.createCard(Card.Value.values()[i], Card.Suite.values()[j]);
                this.cards.add(CF.createCard(Card.Value.values()[i], Card.Suite.values()[j]));          
            }
        }
    }

    public Card getCard() {     
        return cards.remove(0);
    }

    public int cardsLeft() {        
        return cards.size();        
    }   

    public Card getLastCard() {
        return cards.remove(cards.size()-1);
    }
}


CardFactory.java

package model;

public class CardFactory {

    public Card createCard(Card.Value value, Card.Suite suite){
        return new Card(value, suite);
    }

}


DeckTest.java

package model;

import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;

import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;

public class DeckTest {

    @Mock private ArrayList<Card> cards;
    @Mock private Card card;
    @Mock private CardFactory CF;

    @InjectMocks private Deck sut;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
    }   

    @Test   
    public void DeckContains52Cards() {                     
        sut.init();     
        verify(cards, Mockito.times(52)).add(Mockito.any());
    }

    @Test   
    public void getCardIsCalled() {     
        sut.getCard();
        verify(cards).remove(0);        
    }

    @Test   
    public void cardsLeftIsCalled() {       
        sut.cardsLeft();        
        verify(cards).size();       
    }

    @Test   
    public void getLastCardIsCalled() {     
        sut.getLastCard();
        verify(cards).size();       
    }   
}

2 个答案:

答案 0 :(得分:0)

你弄错了。

首先,您要分离依赖项。 CardFactory需要自由生成所需的卡片:

public interface (or abstract class) CardFactory {
    public List<Card> getCards();
}

public class PokerCardFactory implements CardFactory {
  public List<Card> getCards() {
    ArrayList<Card> result = new ArrayList<>();
    for (int i=0; i<13; i++){    
      for (int j=0; j<4; j++){
        result.add(this.createCard(Card.Value.values()[i], Card.Suite.values()[j]));          
      }
    }
    return result;
  }

  private Card createCard(Value value, Suite suite) {
     ...
  }
}

然后注入依赖项(例如在构造函数中)并使用它来生成卡片。

您想要测试Deck而不是PokerCardFactory,因此您需要注入更简单的CardFactory来简化测试。这就是mockito,允许你创建这样一个工厂编写方式的代码。

@Mock private CardFactory cardFactory
@Test
public void numberOfCards {
  ArrayList<Card> cards = new ArrayList();
  cards.add(new Card(Value.Two, Suite.Hearts));
  cards.add(new Card(Value.Three, Suite.Aces));
  when(cardFactory.getCards()).thenReturn(cards); // Now we have a CardFactory that will produce a deck with just two cards.
  Deck deck = new Deck(cardFactory); // Dependency injection.
  assertEquals("The number of cards does not match", 2, deck.getNumberOfCards()); // You have tested `getNumberOfCards`.
} 

答案 1 :(得分:0)

好吧,如果你想测试,你的套牌中的第一张牌是2的心,你的测试应该是这样的:

Deck deck = new Deck();

Card firstCard = deck.getCard();

assertCard(firstCard, Value.Two, Suite.Hearts) // orwhatever

还没有需要嘲笑,是吧? ;)

但这基本上是错误的,因为首先,第二张牌可能是空格的王牌,其次,你不想测试“getCard&#39;”,你想要验证,Deck以正确的顺序调用CardFactory。您无论如何都使用了验证,因此无需解释。 但我还是不喜欢这个测试,因为我本身并没有看到任何价值。只要洗牌有效,它的52张牌并没有复制卡,这个测试已经过时了,但我认为这仍然有利于学习目的。

由于我无法评论,@ SJuan76的回答:此测试没有测试任何东西。我可以切换卡片,我可以删除第一个条目并将第二个条目添加到其位置,或者我甚至可以将两个null添加到新创建的列表中并且测试仍然通过。在重构之后它应该测试的唯一事情就是验证,调用cardFactory.getCards,因为它是唯一能做的,从测试的角度看,必须这样做。