RSpec: stubbing Kernel::sleep?
Is there a way to stub Kernel.sleep in an rspec scenario?
Solution 1:
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.
Solution 2:
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)
Solution 3:
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.
Solution 4:
In pure 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
Solution 5:
Here's the newer way of stubbing Rspec with Kernal::Sleep
.
This is basically an update to the following answer: 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