如何在RSpec中存根Array#sample
的返回值?
鉴于我正在测试的方法包含以下行:
["Rock", "Paper", "Scissors"].sample
我需要类似以下行的内容,这不会破坏行为。
allow(Array).to receive(:sample) { "Rock" }
答案 0 :(得分:0)
我不建议您存储像Array这样常用的类。
您可以通过其他测试和代码获得不可预测的后果。
正如Stefan在他的评论中所建议的那样,你应该将using procs instead of threads
[49062, 41616, 40086, 101224]
提取到单独的包装器方法中,并将此方法存根。
通过这种方法,您将以安全的方式隔离此代码以进行存根。
答案 1 :(得分:0)
正如斯坦尼斯拉夫暗示的那样,如果您存根方法,则需要处理接收该方法的对象。
在这种情况下,它是一个数组的实例,而不是 class 数组,您想要存根,例如:
class MyClass
def pick_random(list)
list.sample
end
end
list = [1,2,3]
expect(list).to receive(:sample).and_return(1)
MyClass.new.pick_random(list)
如果你想以这种方式存根,你需要勤勉地建立你的方法。例如,如果你决定在方法中定义列表,它基本上是从外部隐藏的,并且不可能直接存在于存根中:
class MyClass
def pick_random
[1,2,3].sample
end
end
# This wouldn't work because even though they contain the same elements,
# the list here and in pick_random are different.
expect([1,2,3]).to receive(sample).and_return(1)
MyClass.new.pick_random
这种方法非常适用于各种模拟,但使用基于随机性的方法(如sample
),您也可以使用srand。
答案 2 :(得分:0)
您还可以将随机变量提供给样本方法。通过这样做,您可以使测试具有确定性。
def sample(random = Random::DEFAULT)
["Rock", "Paper", "Scissors"].sample(random: random)
end
specify do
expect(sample(Random.new(1))).to eq('Paper')
end
传递硬编码的随机变量将始终从数组返回相同的元素。根据您的操作系统和Ruby的随机数生成器,它可以是不同的元素。对我来说是“纸”。