【问题标题】:RSpec: stubbing Kernel::sleep?RSpec:存根内核::睡眠?
【发布时间】:2010-11-13 05:18:37
【问题描述】:

有没有办法在 rspec 场景中存根 Kernel.sleep?

【问题讨论】:

  • 您是否在寻找 Kernel::stubs(:sleep) 以外的东西
  • 我想他会希望它工作而不是睡觉,也许会减慢他的测试速度......
  • 这篇文章已经快 10 年了...不再相关
  • @WinstonKotzan 它究竟是如何不再相关的? rspec 不再使用了吗?我错过了什么?

标签: ruby rspec


【解决方案1】:

对于 rspec 版本 1,存根语法已更改。这有效:

allow_any_instance_of(Kernel).to receive(:sleep).and_return("")

当我使用它时。

【讨论】:

    【解决方案2】:

    这是使用 Kernal::Sleep 存根 Rspec 的新方法。

    这基本上是对以下答案的更新:Tony Pitluga's answer to the same question

    class Foo
      def self.some_method
        sleep 5
      end
    end
    
    it "should call sleep" do
      allow_any_instance_of(Foo).to receive(:sleep)
      expect(Foo).to receive(:sleep).with(5)
      Foo.some_method
    end
    

    【讨论】:

      【解决方案3】:

      sleep 的调用不在对象内时(例如在测试 rake 任务时),您可以在前块中添加以下内容(rspec 3 语法)

      allow_any_instance_of(Object).to receive(:sleep)
      

      【讨论】:

        【解决方案4】:

        我无法在这里使用其他解决方案。也许在较新版本的 Ruby 中处理睡眠的方式发生了一些变化,或者其他什么。

        我最终做的是对 Object 类进行猴子补丁,因为它似乎是接收睡眠调用的对象。所以我简单地添加了这个:

        class Object
            def sleep(*args)
            end
        end
        

        所以 sleep 方法现在什么都不做。可能有一些方法可以更好地模拟这个,但如果不模拟可能使用它的每个对象的sleep metohd,我就无法找到一个好的解决方案。

        【讨论】:

        • 请在下面查看我的解决方案。 rspec-mock 在这里,所以你不必猴子补丁
        【解决方案5】:

        如果你在一个对象的上下文中调用 sleep,你应该在对象上存根它,像这样:

        class Foo
          def self.some_method
            sleep 5
          end
        end
        
        it "should call sleep" do
          Foo.stub!(:sleep)
          Foo.should_receive(:sleep).with(5)
          Foo.some_method
        end
        

        关键是,在调用 sleep 的上下文中对任何“self”进行存根。

        【讨论】:

        • 存根被测对象不是一个好主意。例如,请参阅:robots.thoughtbot.com/don-t-stub-the-system-under-test
        • @georgebrock 出于无关的原因,不是吗?我相信this 是最能传达意图的方式。并且必须使用更新的语法。 allow_any_instance_of(Object).to receive(:sleep)
        【解决方案6】:

        我需要存根 require,经过长时间的搜索,我发现唯一对我有用的方法就是这个

        def method_using_sleep
          sleep
          sleep 0.01
        end
        
        it "should use sleep" do
          @expectations = mock('expectations')
          @expectations.should_receive(:sleep).ordered.with()
          @expectations.should_receive(:sleep).ordered.with(0.01)
        
          def sleep(*args)
            @expectations.sleep(*args)
          end
        
          method_using_sleep
        end
        

        【讨论】:

          【解决方案7】:

          在纯 rspec 中:

          before do
            Kernel.stub!(:sleep)
          end
          
          it "should sleep" do
            Kernel.should_receive(:sleep).with(100)
            Object.method_to_test #We need to call our method to see that it is called
          end
          

          【讨论】:

          • 澄清一下,因为这对我没有立即起作用,你必须调用 Kernel.sleep,以便以这种方式模拟它。只是直接调用 sleep 失败
          • 是的,您调用的方法将在其中休眠。
          【解决方案8】:

          如果您使用的是Mocha,那么这样的方法将起作用:

          def setup
            Kernel.stubs(:sleep)
          end
          
          def test_my_sleepy_method
            my_object.take_cat_nap!
            Kernel.assert_received(:sleep).with(1800) #should take a half-hour paower-nap
          end
          

          或者,如果您使用的是rr

          def setup
            stub(Kernel).sleep
          end
          
          def test_my_sleepy_method
            my_object.take_cat_nap!
            assert_received(Kernel) { |k| k.sleep(1800) }
          end
          

          可能不应该使用单元测试来测试更复杂的线程问题。但是,在集成测试中,请使用真正的 Kernel.sleep,这将帮助您找出复杂的线程问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-16
            • 2011-09-23
            • 2021-10-15
            • 2012-04-07
            • 1970-01-01
            相关资源
            最近更新 更多