Hello,
I’m having a problem with RSpec when using the “lambda should change
behavior”.
This is happening in a Rails 2.3.4 app and I’m running the following
in my test environment:
‘cucumber’, :version => ‘0.4.2’
‘faker’, :version => ‘0.3.1’
‘notahat-machinist’, :lib => ‘machinist’, :version => ‘1.0.3’
“remarkable_rails”, :lib => false
‘rspec’, :lib => false, :version => ‘1.2.9’
‘rspec-rails’, :lib => false, :version => ‘1.2.9’
‘jtrupiano-timecop’, :lib => ‘timecop’, :version => ‘0.3.0’
‘webrat’, :lib => false, :version => ‘0.5.1’
‘fakeweb’, :lib => false, :version => ‘1.2.6’
In my application, I have a Post model that is using Rubyist’s AASM
gem. The aasm column is defined as ‘state’. The other column of note
is ‘published_at’; this is defined as a datetime.
These are the settings for the state machine:
aasm_column :state
aasm_initial_state :draft
aasm_state :draft
aasm_state :published, :enter => :set_published
aasm_event :publish do
transitions :to => :published, :from => :draft
end
set_published is a method that is defined as:
def set_published
self.update_attributes(:published_at => Time.now)
end
For those that are unfamiliar with Rubyist’s AASM, defining an
aasm_event gives you an bang instance method with the same name of the
aasm_event. For example, I have :publish defined as an aasm_event and
because of this I can call the publish! method on an instance of a
Post. This will change the state from ‘draft’ to ‘published’. It will
also call the set_published method as defined by the :enter statement.
This is my first spec attempt. I’ve removed all of the post attributes
for brevity.
describe “AASM States” do
before(:each) do
@post = Post.create([snip…post attributes here])
end
it “should set the publish date to now when transitioning to
published” do
lambda { @post.publish! }.should change(@post,
:published_at).from(nil).to(Time.now)
end
end
This fails with a message like the following:
published_at should have been changed to Sat Nov 07 15:02:00 -0800
2009, but is now Sat Nov 07 15:02:00 -0800 2009
blink blink
They appear to be the same.
Just in case the time was being altered by milliseconds that I
couldn’t see, I tried using jtrupiano’s Timecop gem to freeze time and
check against the frozen time.
it "should set the publish date to now when transitioning to
published" do
time = Time.now
Timecop.freeze(time)
lambda { @post.publish! }.should change(@post,
:published_at).from(nil).to(time)
Timecop.return
end
This still gives me the same failure message. For those unfamiliar
with Timecop, here is how it works (in the console):
require ‘Timecop’
=> []time = Timecop.freeze(Time.now)
=> Sat Nov 07 15:07:32 -0800 2009sleep(10)
=> 10time == Time.now
=> trueTimecop.return
=> Sat Nov 07 15:08:09 -0800 2009time == Time.now
=> false
In development, I know that the published_at time is truly
transitioning from nil to an actual time, I just don’t know why it’s
failing in the spec and even stranger when RSpec tells me that they
are the (supposedly) the same.
From the development console:
p = Post.new([snip…post attributes here])
p.save
=> truep.published_at
=> nilp.publish!
=> truep.published_at
=> Sat Nov 07 15:10:22 -0800 2009
Is there something that I’m missing?
Thank you in advance for your help,
Carlos