Cucumber step definition tip: Stubbing time

When writing Cucumber scenarios, you'll occasionally need to describe a behavior that is dependent on time passing. For example, at weplay we want to ensure that a password reset link expires after one week.

In a RSpec code example, you might be used to stubbing time in this situation:

1
2
3

now = Time.now
Time.stub!(:now).and_return(now + 8.days)

This doesn't work out-of-the-box in a Cucumber step definition. By default, Cucumber doesn't include any of RSpec's mocking or stubbing support. This makes sense because Cucumber is a tool for acceptance testing (full stack), where stubbing and especially mocking should be discouraged and only used for very specific purposes (like stubbing time!).

If you find yourself in this situation, you can enable RSpec's stubbing support in your Cucumber step definitions by adding the following code to env.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

require "spec/mocks"

Before do
  $rspec_mocks ||= Spec::Mocks::Space.new
end

After do
  begin
    $rspec_mocks.verify_all
  ensure
    $rspec_mocks.reset_all
  end
end

Now you can go ahead and create a time_steps.rb like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

When /^(\d+) minutes pass$/ do |minutes|
  now = Time.now
  Time.stub!(:now).and_return(now + minutes.to_i.minutes)
end

When /^(\d+) hours pass$/ do |hours|
  now = Time.now
  Time.stub!(:now).and_return(now + hours.to_i.hours)
end

When /^(\d+) days pass$/ do |days|
  now = Time.now
  Time.stub!(:now).and_return(now + days.to_i.days)
end

RSpec will clear your time stub at the end of each scenario.

5 Responses to “Cucumber step definition tip: Stubbing time”

  1. # Sebastian Says:

    I prefer to use Time.freeze (there is a version here http://snippets.dzone.com/posts/show/4776)

  2. # Mark Wilden Says:

    I was using Time.stub(:now) and we had some baffling feature failures on the build server that didn’t occur on any local box. It turned out that the problem was the order of the features – on the build machine, the feature that stubbed Time was interfering with subsequent features. This code is just what we needed – thanks!

  3. # Vaskas Says:

    Hi Bryan! Sorry for offtopic. Did you solve this problem: rubygems.rb:723:in `getpwuid’: can’t find user for 501 (ArgumentError) (Yes, user 501 exists) I am experiencing exactly the same behavior when child processes stop working after some time..

  4. # schlick Says:

    Awesome! I used it straight away and it worked like a charm.

  5. # Dr Nic Says:

    For using mocha with cucumber, the following pastie seems to work: http://gist.github.com/80554