试图学习如何在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();
}
}
你弄错了。
首先,您将依赖项分开。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`.
}
好吧,如果要测试,甲板上的第一张卡是两个的心,您的测试应该看起来像这样:
Deck deck = new Deck();
Card firstCard = deck.getCard();
assertCard(firstCard, Value.Two, Suite.Hearts) // orwhatever
还没有模拟的需要,是吗?;)
但这基本上是错误的,因为首先,第二张卡可以是空间的王牌,其次,您不想测试" getCard',您想 verify 甲板以正确的顺序调用卡片。无论如何,您都使用了验证,因此无需解释。但是我无论如何都不喜欢这个测试,因为我本身没有任何值。只要混车工作起作用,它是52张卡片,没有复制卡,该测试已经过时了,但我猜仍然适合学习目的。
。由于我无法评论, @sjuan76的答案:此测试没有测试任何内容。我可以切换卡,可以删除第一个条目,然后将第二个输入添加到其位置,或者甚至可以将两个null添加到新创建的列表中,并且测试仍然通过。重构后它唯一应该测试的是验证,cardFactory.getCard被称为,因为这是唯一的事情,从测试的角度来看,必须做。