【问题标题】:How to stub rand in rspec?如何在rspec中存根rand?
【发布时间】:2019-06-17 01:28:07
【问题描述】:

我正在使用 Ruby 2.3.4 和 rspec 3.6.0。

我正在为使用rand(10000..99999) 的对象编写测试。我在rand 上找不到任何文档来查看它属于哪个对象。我尝试存根 KernelObjectRandom(见下文),但我的所有尝试都没有导致 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)

感谢任何帮助。

【问题讨论】:

    标签: ruby rspec


    【解决方案1】:

    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 实例,因为这是 MyRandom#random 中的 self 对象方法。

    测试时,您可以在此实例上存根 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
    

    【讨论】:

    • 有趣的是,我不知道 ruby​​ 将自己调用的 rand 分配给它所调用的对象。成功了,谢谢!!
    • 这对所有模块都是一样的。如果您在类中包含模块,则在类实例上调用方法。 Kernel 在这里没有什么不同。唯一的“特殊”是 Kernel 模块默认包含在所有对象中,允许在任何地方调用它的方法。由于它仍然是一个普通模块,但是您可以像对任何其他方法一样覆盖每个类的方法(尽管您应该小心这样做)。
    【解决方案2】:

    这行得通:

    allow_any_instance_of(Object).to receive(:rand).and_return(12345)
    

    【讨论】:

      【解决方案3】:

      有时很难存根位于另一个对象深处的对象。所以我发现这种方法有助于简化事情:

      class Worker
        def self.rand(*args)
          # Calls the actual rand method
          Kernel.rand(*args)
        end
      
        def perform
          # Calls private method rand -> Worker.rand
          rand(1..5)
        end
      
        private
      
        def rand(*args)
          self.class.rand(*args)
        end
      end
      

      这让我们可以轻松地存根:

      allow(Worker).to receive(:rand).and_return(2)
      
      expect(Worker.new.perform).to eq 2
      

      【讨论】:

        猜你喜欢
        • 2015-10-14
        • 2017-03-27
        • 1970-01-01
        • 2013-06-16
        • 2019-03-30
        • 2015-04-16
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        相关资源
        最近更新 更多