RSpec: stubbing Kernel::sleep?

If you are calling sleep within the context of an object, you should stub it on the object, like so:

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

The key is, to stub sleep on whatever "self" is in the context where sleep is called.


When the call to sleep is not within an object (while testing a rake task for example), you can add the following in a before block (rspec 3 syntax)

allow_any_instance_of(Object).to receive(:sleep)

If you're using Mocha, then something like this will work:

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

Or if you're using 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

You probably shouldn't be testing more complex threading issues with unit tests. On integration tests, however, use the real Kernel.sleep, which will help you ferret out complex threading issues.

Tags:

Ruby

Rspec