tags:

views:

358

answers:

4

Is there a way to stub Kernel.sleep in an rspec scenario?

+1  A: 

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.

James A. Rosen
+3  A: 

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
railsninja
To 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
A: 

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
tig
+2  A: 

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.

Worked great for me, cheers!
opsb