如何使用RSpec存储#sample?

时间:2017-10-14 13:36:10

标签: ruby rspec

如何在RSpec中存根Array#sample的返回值?

鉴于我正在测试的方法包含以下行:

["Rock", "Paper", "Scissors"].sample

我需要类似以下行的内容,这不会破坏行为。

allow(Array).to receive(:sample) { "Rock" }

3 个答案:

答案 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的随机数生成器,它可以是不同的元素。对我来说是“纸”。