如何在Java中测试含随机输入的代码?以Yahtzee游戏ResultCalculator为例
测试Yahtzee风格游戏ResultCalculator的实用思路
针对你遇到的问题,核心是不要把随机逻辑和结果计算逻辑绑定测试,实际开发中通常这么处理:
1. 直接测试ResultCalculator(最推荐)
ResultCalculator的核心职责是接收确定的骰子组合,输出对应的有效结果。完全不需要通过Draw或Die的随机流程来测试它——直接构造确定的骰子值集合传给它即可:
- 测试Large Straight:传入
[1,2,3,4,5]或[2,3,4,5,6],验证返回有效;传入[1,2,3,4,4]验证返回无效。 - 测试Yahtzee:传入
[5,5,5,5,5]验证有效,传入[5,5,5,5,6]验证无效。 - 其他规则(比如Full House、Small Straight等)同理,把所有可能的有效/无效组合列出来,逐个构造输入测试。
这种方式最直接,完全绕开随机逻辑,精准测试ResultCalculator的核心计算能力。
2. 若要测试Draw与ResultCalculator的协作,用依赖注入控制随机
如果需要验证Draw生成骰子后调用ResultCalculator的完整流程,可以修改Die类让Random可替换:
public class Die { private Value value; private int valueAsInt; private Random random; // 生产环境默认构造 public Die() { this.random = new Random(); } // 测试用构造,传入可控的Random实例 public Die(Random random) { this.random = random; } public void rollDie() { int result = random.nextInt(1, 7); value = switch (result) { case 1 -> Value.ONE; case 2 -> Value.TWO; case 3 -> Value.THREE; case 4 -> Value.FOUR; case 5 -> Value.FIVE; case 6 -> Value.SIX; }; valueAsInt = result; } }
测试时可以:
- 传入固定种子的Random,确保每次掷骰子结果一致:
Random fixedRandom = new Random(123);,用这个实例创建Die后,调用Draw的rollDice就能得到确定的骰子组合,再验证ResultCalculator的输出。 - 用Mock工具(比如Mockito)让Random的
nextInt返回固定值,直接指定每个骰子的点数:Random mockRandom = Mockito.mock(Random.class); Mockito.when(mockRandom.nextInt(1,7)).thenReturn(1,2,3,4,5); // 指定5个骰子的点数 Die die = new Die(mockRandom);
3. 覆盖所有规则场景与边界情况
不管用哪种测试方式,都要把Yahtzee规则的所有情况覆盖到位:
- 所有单数字组合(全1、全2等)的Yahtzee判定
- Large Straight的两种有效序列,以及各种无效序列(缺数、有重复数)
- Full House的有效(3个同数+2个同数)和无效(4个同数+1个、全不同等)情况
- Small Straight的各种有效(1-2-3-4、2-3-4-5等)和无效情况
- 其他得分项(三个同数、四个同数、Chance)的判定
内容的提问来源于stack exchange,提问作者Jules
相关产品推荐
相关产品推荐

