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.