ski*_*iwi 5 java junit unit-testing
考虑以下类:
public class Deck {
private final Queue<Card> queue = new LinkedList<>();
public Deck() { }
public Deck(final Collection<Card> cards) {
Objects.requireNonNull(cards);
queue.addAll(cards);
}
public void add(final Card card) {
Objects.requireNonNull(card);
queue.add(card);
}
public void addAll(final Collection<Card> cards) {
Objects.requireNonNull(cards);
queue.addAll(cards);
}
public void shuffle() {
Collections.shuffle((List<Card>)queue);
}
public Card take() {
return queue.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
我将如何对shuffle()方法进行单元测试?我正在使用 JUnit 4 进行测试。
我有以下选择:
shuffle()以查看它不会生成异常。shuffle()并检查牌组是否真的被洗牌了。选项 2 的示例伪代码:
while notShuffled
create new Deck
take cards and check if they are shuffled
Run Code Online (Sandbox Code Playgroud)
这里唯一的罪魁祸首是,在执行为选项 2(也继承了选项 1)编写的测试时,如果 shuffle 没有按预期工作,那么代码执行将永远不会停止。
我将如何解决这个问题?是否有可能限制 JUnit 测试中的执行时间?
目前,您的类与函数紧密耦合Collections.shuffle。静态函数因使测试变得更加困难而臭名昭著。(最重要的是,您测试没有意义Collections.shuffle;大概,它可以正常工作。)
为了解决这个问题,你可以在你的班级中为这个改组功能引入一个接缝。这是通过将shuffle功能提取为角色(由接口表示)来完成的。例如:
public interface ICardShuffler {
void shuffle(List<Card> cards);
}
Run Code Online (Sandbox Code Playgroud)
然后,您的Deck类可以配置为保留对该接口某些实现的实例的引用,并在必要时调用它:
public class Deck {
private final Queue<Card> queue = new LinkedList<>();
private ICardShuffler cardShuffler;
public Deck(ICardShuffler cardShuffler) {
this.cardShuffler = cardShuffler;
}
...
public void shuffle() {
cardShuffler.shuffle((List<Card>)queue);
}
...
Run Code Online (Sandbox Code Playgroud)
这允许您的单元测试使用test double,如模拟对象,来验证预期的行为是否发生(即,在提供的上shuffle调用)。shuffleICardShuffler
最后,您可以将当前功能移动到此接口的实现中:
public class CollectionsCardShuffler implements ICardShuffler {
public void shuffle(List<Card> cards) {
Collections.shuffle(cards);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:除了便于测试之外,此接缝还允许您实现新的 shuffle 方法,而无需修改Deck.
| 归档时间: |
|
| 查看次数: |
4950 次 |
| 最近记录: |