【问题标题】:How do I create a unit test for a constructor with Random class in javajava - 如何在java中为带有Random类的构造函数创建单元测试
【发布时间】:2020-10-18 09:00:18
【问题描述】:

这是我的构造函数

    public Dice(final int numOfDice)
    {   
        if(numOfDice < Skunk.LOWEST_NUM_OF_DICE && numOfDice > Skunk.HIGHEST_NUM_OF_DICE)
        {
            throw new IllegalArgumentException("the number of dice must be " + Skunk.LOWEST_NUM_OF_DICE + " or " + Skunk.HIGHEST_NUM_OF_DICE);
        }
        
        this.numOfDice = numOfDice;
        
        dice = new int[this.numOfDice];
        
        Random  r;
        r = new Random();
                
        for(int i=0; i<this.numOfDice; i++)
        {
            dice[i] = r.nextInt(HIGHEST_NUMBER_ON_DIE-LOWEST_NUMBER_ON_DIE+OFFSET) + LOWEST_NUMBER_ON_DIE;
        }
    }

我希望能够编写一个单元测试,在其中将骰子初始化为特定值。但是,我似乎无法弄清楚如何控制 Random 类。我在构造函数上尝试了@Override,但它只适用于函数。我尝试将 for 循环移动到一个名为 roll 的方法并在其上使用 @Override,但 @Override 不适用于构造函数中调用的函数。

我已经安装了 Mockito 并尝试遵循此处第一个答案中发布的建议: How to test a method that uses Random(), without arguments and return value, using JUnit or Mockito 但我不知道 Mockito 是如何工作的。

【问题讨论】:

    标签: java eclipse unit-testing junit mockito


    【解决方案1】:

    使 Random 对象成为一个字段并模拟它:

    private Random random = new Random();
    
    public Dice(final int numOfDice)
    {   
        if(numOfDice < Skunk.LOWEST_NUM_OF_DICE && numOfDice > Skunk.HIGHEST_NUM_OF_DICE)
        {
            throw new IllegalArgumentException("the number of dice must be " + Skunk.LOWEST_NUM_OF_DICE + " or " + Skunk.HIGHEST_NUM_OF_DICE);
        }
        
        this.numOfDice = numOfDice;
        
        dice = new int[this.numOfDice];
        for(int i=0; i<this.numOfDice; i++)
        {
            dice[i] = random.nextInt(HIGHEST_NUMBER_ON_DIE-LOWEST_NUMBER_ON_DIE+OFFSET) + LOWEST_NUMBER_ON_DIE;
        }
    }
    

    将随机替换为您的测试的模拟。

    【讨论】:

    • 谢谢!两个问题:(1)你不应该在构造函数中初始化实例变量吗?所以我可以有私人随机随机;上面和 random = new Random() 在构造函数中。 (2) 你如何模拟 Random?如果你能告诉我或提供一个很好的参考,那就太好了。我是 Mockito 的新手。
    • 例如,如果我想将我的骰子设置为 1-5-1,我该怎么做?
    • 没有这样的“规则”说您必须在构造函数中分配字段 - 您可以根据需要在声明中分配字段。您不应该在您的产品代码中包含任何与测试相关的内容,但是通过这种方式,您可以使其可测试。您可以让您的模拟库创建一个看起来像 Random 的模拟对象并将其分配给该字段。从此咨询您的模拟框架库。我,我使用 Spock,它杀死了旧的模拟框架。
    【解决方案2】:

    我不确定为什么需要测试 Random 的结果,主要目的应该是测试您的 dice[] 是否具有指定范围内的值。

    我建议您调用该方法并读取 dice[] 中的所有值并检查每个值是否存在于您指定的范围内,

    范围:0 to ((HIGHEST_NUMBER_ON_DIE-LOWEST_NUMBER_ON_DIE+OFFSET) + LOWEST_NUMBER_ON_DIE)

    【讨论】:

    • 我已经做到了。但是,我想测试我的 getScore() 函数,该函数根据骰子的结果分配分数。为此,我需要知道掷出的骰子是什么。
    • 请看,即使您的方法是直接调用 random 并获取其 int 值的“getScore”,您也不是在测试您的代码,而是在测试 Math.Random 类。我建议你不必这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多