Is there a way to stub Kernel.sleep in an rspec scenario?
-
Are you looking for something beyond Kernel::stubs(:sleep) – Sam Saffron Jul 23 '09 at 00:16
-
I'd imagine he'd be wanting it to work and not sleep, maybe slowing his test... – Rich Aug 31 '17 at 03:04
-
This post is almost 10 years old... no longer relevant – Winston Kotzan Sep 13 '18 at 18:23
-
2@WinstonKotzan how exactly is it no longer relevant? Is rspec not used anymore? What did I miss? – hraban Dec 04 '19 at 17:10
9 Answers
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.
-
Stubbing the object under test isn't a good idea. For examples, see: http://robots.thoughtbot.com/don-t-stub-the-system-under-test – georgebrock Jul 02 '14 at 13:40
-
4@georgebrock for nonrelevant reason, isn't it? I believe [this](http://stackoverflow.com/a/27749263/52499) is the way that conveys intention best. And must be using newer syntax. `allow_any_instance_of(Object).to receive(:sleep)` – x-yuri Jan 02 '15 at 23:54
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)

- 12,971
- 2
- 41
- 73
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

- 5,496
- 1
- 28
- 35
-
13To clarify, because this didn't work for me immediately, you must call Kernel.sleep, in order to mock it this way. Just calling sleep directly fails – Jeff D Jul 28 '10 at 04:02
-
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.

- 64,193
- 61
- 179
- 261
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

- 4,609
- 4
- 17
- 30
For rspec version 1, the stubbing syntax has changed. This works:
allow_any_instance_of(Kernel).to receive(:sleep).and_return("")
When I use it.

- 87
- 1
- 2
I needed to stub require and after long searching I found that the only way that worked for me is this
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

- 25,841
- 10
- 64
- 96
I was not able to get the other solutions here to work. Maybe something have changed in the way sleep is handled in newer versions of Ruby, or something else.
What I ended up doing was to monkey-patch the Object class as it appears that this is what receives the sleep calls. So I simply added this:
class Object
def sleep(*args)
end
end
So the sleep method now does nothing in stead of something. There might be some way of mocking this better, but I was not able to find a good solution without mocking the sleep metohd
of every single object that potentially used it.

- 12,420
- 9
- 82
- 110
-
Please see my solution bellow. rspec-mock is here so you don't have to monkey-patch – Benjamin Bouchet Jan 02 '15 at 22:17
Since Kernel
is an ancestor of all Objects, one should be able to mock the inherited sleep
method on the class under test.
MyClass.ancestors --> [MyClass, Object, PP::ObjectMixin, Kernel, BasicObject]
The mock can be accomplished with code similar to this.
before do
allow(described_class).to receive(:sleep).and_return('')
end
The following more detailed example shows mocking sleep
for when it is called within class and instance methods. Would enjoy hearing comments from more experienced Ruby developers.
Class:
class MyClass
class << self
def klass_action(sleep_seconds)
sleep(sleep_seconds)
end
end
def self.class_action(sleep_seconds)
sleep(sleep_seconds)
end
def do_some_action(sleep_seconds)
sleep(sleep_seconds)
end
end
Tests:
describe MyClass, focus: true do
subject { MyClass.new }
let(:sleep_seconds) { 12 }
context 'sleep called from an instance' do
before do
allow(subject).to receive(:sleep).and_return('')
end
it 'sleeps for the requested number of seconds' do
subject.do_some_action(sleep_seconds)
expect(subject).to have_received(:sleep).with(sleep_seconds)
end
end
context 'sleep called from a class' do
before do
allow(described_class).to receive(:sleep).and_return('')
end
it 'class method sleeps for the requested number of seconds' do
described_class.class_action(sleep_seconds)
expect(described_class).to have_received(:sleep).with(sleep_seconds)
end
it 'klass method sleeps for the requested number of seconds' do
described_class.klass_action(sleep_seconds)
expect(described_class).to have_received(:sleep).with(sleep_seconds)
end
end
end

- 166
- 2
- 5