java - 随机数方法的 Junit 测试

标签 java junit mockito

我正在尝试为一个方法创建一个 Junit 测试,该方法使用一个简单的随机数来调用另一个简单的方法,该方法根据参数的值返回石头、布或剪刀。

我不知道该怎么做。

public class Play {

    public String player2Choice() {

        // Create a Random object.
        Random random = new Random();

        // Ramdon number between 1-3
        int numberChoice = random.nextInt(3) + 1;

        // Return the player random choice
        return getItem(numberChoice);
    }

    public String getItem(int numberChoice) {

        String item;

        switch (numberChoice) {
        case 1:
            item = "rock";
            break;
        case 2:
            item = "scissors";
            break;
        case 3:
            item = "paper";
            break;
        default:
            item = null;
        }

        return item;
    }
}

现在我有这个测试:

Play play;

@Before
public void setup() {

    play = new Play();
}

@Test
public void testPlayer2Choice() {

    int param = 1;
    Play play2 = Mockito.mock(Play.class);


    play2.getItem(param);
    Mockito.verify(play2).getItem(param);

    String result = play.player2Choice();

    assertEquals("rock", result);


}

最佳答案

PlayRandom 紧密耦合,它实际上无法控制。这使得测试特定的数字选择变得困难。

如果目标是测试给定1的数字选择,player2Choice返回“rock”,然后更多地控制如此-需要称为随机性。

public interface RandomInteger {
    int nextInt(int max);
}

接口(interface)的实现将封装一个实际的Random类并代理所需的行为/功能

public class RandomIntegerImplementation : RandomInteger {
    private Random random ;

    public RandomIntegerImplementation() {
        // Create a Random object.
        random  = new Random();
    }

    public int nextInt(int max) {
        return random.nextInt(max);
    }
}

然后需要重构 Play 以明确依赖于现在的抽象随机提供程序。

public class Play {
    private RandomInteger random;

    public Play(RandomInteger random) {
        this.random = random;
    }

    public String player2Choice() {
        // Ramdon number between 1-3
        int numberChoice = random.nextInt(3) + 1;

        // Return the player random choice
        return getItem(numberChoice);
    }

    //...code removed for brevity
}

现在,如果要满足上述测试用例,则可以模拟依赖关系以使其按预期运行。

RandomInteger random;

Play play;

@Before
public void setup() {
    random = Mockito.mock(RandomInteger.class);
    play = new Play(random);
}

@Test
public void testPlayer2Choice_Given_Zero() {
    //Arrange
    String expected = "rock";
    int numberChoice = 0;

    when(random.nextInt(3)).thenReturn(numberChoice);

    //Act
    String actual = play.player2Choice();

    //Assert
    Mockito.verify(play).getItem(numberChoice + 1);
    assertEquals(expected, actual);
}

这对于开始来说应该足够了。对于其他测试用例也可以这样做。

最终 getItem 也可以重构为自己的服务,但这超出了原始问题的范围。

关于java - 随机数方法的 Junit 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48719551/

相关文章:

java - Mockito thenReturn 返回相同的实例

java - 如何在java中模拟单个语句

java - 无状态 EJB 中的静态成员与实例成员

java - 与 Jersey 错误处理达成协议(protocol)

java - JMenuItem的单元测试

java - org.hibernate.MappingNotFoundException : resource: com/ypd/a/entity/Employee. hbm.xml 未找到

java - Mockito:获取模拟对象中字段的值

Java-多边形和线的交点

java - 添加到 JComponent 的绘制 JComponent 的问题

java - 如何使用模拟覆盖@Produces