2017-08-18 27 views
1

我使用Ruby 2.3.4和rspec 3.6.0。如何在rspec中存根rand?

我正在为使用rand(10000..99999)的对象编写测试。我找不到rand上的任何文档来查看它是哪个对象的一部分。我试图剔除Kernel,ObjectRandom(见下文),但我的任何尝试都没有导致rand被剔除。

allow(Kernel).to receive(rand).and_return(12345) 
allow(Object).to receive(rand).and_return(12345) 
allow(Random).to receive(rand).and_return(12345) 

任何帮助表示赞赏。

回答

5

rand确实在Kernel模块中实现。但是,在代码中调用方法时,方法接收器实际上是您自己的对象。

假设下面的类:

class MyRandom 
    def random 
    rand(10000..99999) 
    end 
end 

my_random = MyRandom.new 
my_random.random 
# => 56789 

当调用my_random.random,所述接收器(即在其上调用方法上的对象)的rand方法的又是my_random实例,因为这是被self对象在MyRandom#random方法中。

当测试这一点,您可以在此存根rand方法在这种情况下:

describe MyRandom do 
    let(:subject) { described_class.new } 

    describe '#random' do 
    it 'calls rand' do 
     expect(subject).to receive(:rand).and_return(12345) 
     expect(subject.random).to eq 12345 
    end 
    end 
end 
+0

有趣的是,我不知道红宝石分配'rand'调用它自己来这就是所谓的对象。这工作,谢谢你! – theartofbeing

+0

这对所有模块都是一样的。如果将模块包含在类中,则会在类实例上调用方法。 'Kernel'在这里没有什么不同。这只是“特殊的”,因为默认情况下所有对象都包含“Kernel”模块,从而允许在任何地方调用其方法。因为它仍然是一个普通的模块,所以你可以像使用其他方法一样覆盖每个类的方法(尽管你应该小心这样做)。 –