tatyree
2009-Jan-29 18:08 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
Even if this is a bug, it''s a pretty obscure one. It was frustrating the hell out of me until I found a workaround, so I thought I''d just post the details: Given a find like this: def self.find_old User.all(:conditions => [''updated_at <= ?'',Time.now - 1.day) ... Trying to set a message expectation will always fail: it "should find users" do User.should_receive(:all).with({:conditions => [''updated_at <= ?'',Time.now - 1.day]}) User.find_old ... with the error: Mock ''Class'' expected :all with ({:conditions=>["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) but received it with ({:conditions=> ["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) Expected and received here are identical. The only workaround I''ve found (the example here is simplified, but the datetime in the model where I discovered the bug is critical and so needs to be spec''d) is to wrap the Time call and the expectation in another format: User.all(:conditions => [''updated_at <= ?'',(Time.now - 1.day).xmlschema]) and it "should find users" do User.should_receive(:all).with({:conditions => [''updated_at <= ?'', (Time.now - 1.day).xmlschema]}) I''m on rspec 1.1.12 on rails 2.1.0 and I''m guessing the + in the formatted datetime is playing hell with a regexp somewhere. Unfortunately, I don''t have time to dig in to it myself right now. I was seeing the same behaviour when I tried hash_including (:conditions => [''updated_at <= ?'',Time.now - 1.day]) as part of the expectation. Thanks, Todd
David Chelimsky
2009-Jan-29 18:41 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Thu, Jan 29, 2009 at 12:08 PM, tatyree <todd at snappl.co.uk> wrote:> Even if this is a bug, it''s a pretty obscure one. It was frustrating > the hell out of me until I found a workaround, so I thought I''d just > post the details: > > Given a find like this: > > def self.find_old > User.all(:conditions => [''updated_at <= ?'',Time.now - 1.day) > ... > > Trying to set a message expectation will always fail: > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at > <= ?'',Time.now - 1.day]}) > User.find_old > ... > > with the error: > Mock ''Class'' expected :all with ({:conditions=>["updated_at <= ?", > Wed Jan 28 17:59:02 +0000 2009]}) but received it with ({:conditions=> > ["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) > > Expected and received here are identical. > > The only workaround I''ve found (the example here is simplified, but > the datetime in the model where I discovered the bug is critical and > so needs to be spec''d) is to wrap the Time call and the expectation in > another format: > > User.all(:conditions => [''updated_at <= ?'',(Time.now - > 1.day).xmlschema]) > > and > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at <= ?'', > (Time.now - 1.day).xmlschema]}) > > I''m on rspec 1.1.12 on rails 2.1.0 and I''m guessing the + in the > formatted datetime is playing hell with a regexp somewhere. > Unfortunately, I don''t have time to dig in to it myself right now. > > I was seeing the same behaviour when I tried hash_including > (:conditions => [''updated_at <= ?'',Time.now - 1.day]) as part of the > expectation.The problem is a display problem - the Time objects are actually different by some milliseconds, but you don''t see that in the feedback. Try this: now = Time.now Time.stub!(:now).and_return(now) Then both calls will return the same object.> > > Thanks, > Todd > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090129/df78059e/attachment.html>
aslak hellesoy
2009-Jan-29 18:42 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Thu, Jan 29, 2009 at 7:08 PM, tatyree <todd at snappl.co.uk> wrote:> Even if this is a bug, it''s a pretty obscure one. It was frustrating > the hell out of me until I found a workaround, so I thought I''d just > post the details: > > Given a find like this: > > def self.find_old > User.all(:conditions => [''updated_at <= ?'',Time.now - 1.day) > ... > > Trying to set a message expectation will always fail: > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at > <= ?'',Time.now - 1.day]}) > User.find_old > ... > > with the error: > Mock ''Class'' expected :all with ({:conditions=>["updated_at <= ?", > Wed Jan 28 17:59:02 +0000 2009]}) but received it with ({:conditions=> > ["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) > > Expected and received here are identical. >No they are not. They are milliseconds apart. You should *always* stub Time.now in tests. Aslak> The only workaround I''ve found (the example here is simplified, but > the datetime in the model where I discovered the bug is critical and > so needs to be spec''d) is to wrap the Time call and the expectation in > another format: > > User.all(:conditions => [''updated_at <= ?'',(Time.now - > 1.day).xmlschema]) > > and > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at <= ?'', > (Time.now - 1.day).xmlschema]}) > > I''m on rspec 1.1.12 on rails 2.1.0 and I''m guessing the + in the > formatted datetime is playing hell with a regexp somewhere. > Unfortunately, I don''t have time to dig in to it myself right now. > > I was seeing the same behaviour when I tried hash_including > (:conditions => [''updated_at <= ?'',Time.now - 1.day]) as part of the > expectation. > > Thanks, > Todd > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Aslak (::)
Nick Hoffman
2009-Jan-29 19:04 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On 29/01/2009, at 1:41 PM, David Chelimsky wrote:> On Thu, Jan 29, 2009 at 12:08 PM, tatyree <todd at snappl.co.uk> wrote: > Even if this is a bug, it''s a pretty obscure one. It was frustrating > the hell out of me until I found a workaround, so I thought I''d just > post the details: > > Given a find like this: > > def self.find_old > User.all(:conditions => [''updated_at <= ?'',Time.now - 1.day) > ... > > Trying to set a message expectation will always fail: > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at > <= ?'',Time.now - 1.day]}) > User.find_old > ... > > with the error: > Mock ''Class'' expected :all with ({:conditions=>["updated_at <= ?", > Wed Jan 28 17:59:02 +0000 2009]}) but received it with ({:conditions=> > ["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) > > Expected and received here are identical. > > The only workaround I''ve found (the example here is simplified, but > the datetime in the model where I discovered the bug is critical and > so needs to be spec''d) is to wrap the Time call and the expectation in > another format: > > User.all(:conditions => [''updated_at <= ?'',(Time.now - > 1.day).xmlschema]) > > and > > it "should find users" do > User.should_receive(:all).with({:conditions => [''updated_at <= ?'', > (Time.now - 1.day).xmlschema]}) > > I''m on rspec 1.1.12 on rails 2.1.0 and I''m guessing the + in the > formatted datetime is playing hell with a regexp somewhere. > Unfortunately, I don''t have time to dig in to it myself right now. > > I was seeing the same behaviour when I tried hash_including > (:conditions => [''updated_at <= ?'',Time.now - 1.day]) as part of the > expectation. > > The problem is a display problem - the Time objects are actually > different by some milliseconds, but you don''t see that in the > feedback. > > Try this: > > now = Time.now > Time.stub!(:now).and_return(now) > > Then both calls will return the same object.You''re too fast, David and Aslak! =P Todd, I fell prey to the same problem a few months ago. As David and Aslak suggested, just stub out Time#now . Eg: it ''should do something'' do now = Time.now Time.stub!(:now).and_return now User.should_receive(:all).with(:conditions => [''updated_at <= ?'', now - 1.day]) User.all(:conditions => [''updated_at <= ?'', Time.now - 1.day]) end Cheers, Nick
Pat Maddox
2009-Jan-30 03:32 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Thu, Jan 29, 2009 at 10:41 AM, David Chelimsky <dchelimsky at gmail.com> wrote:> > > On Thu, Jan 29, 2009 at 12:08 PM, tatyree <todd at snappl.co.uk> wrote: >> >> Even if this is a bug, it''s a pretty obscure one. It was frustrating >> the hell out of me until I found a workaround, so I thought I''d just >> post the details: >> >> Given a find like this: >> >> def self.find_old >> User.all(:conditions => [''updated_at <= ?'',Time.now - 1.day) >> ... >> >> Trying to set a message expectation will always fail: >> >> it "should find users" do >> User.should_receive(:all).with({:conditions => [''updated_at >> <= ?'',Time.now - 1.day]}) >> User.find_old >> ... >> >> with the error: >> Mock ''Class'' expected :all with ({:conditions=>["updated_at <= ?", >> Wed Jan 28 17:59:02 +0000 2009]}) but received it with ({:conditions=> >> ["updated_at <= ?", Wed Jan 28 17:59:02 +0000 2009]}) >> >> Expected and received here are identical. >> >> The only workaround I''ve found (the example here is simplified, but >> the datetime in the model where I discovered the bug is critical and >> so needs to be spec''d) is to wrap the Time call and the expectation in >> another format: >> >> User.all(:conditions => [''updated_at <= ?'',(Time.now - >> 1.day).xmlschema]) >> >> and >> >> it "should find users" do >> User.should_receive(:all).with({:conditions => [''updated_at <= ?'', >> (Time.now - 1.day).xmlschema]}) >> >> I''m on rspec 1.1.12 on rails 2.1.0 and I''m guessing the + in the >> formatted datetime is playing hell with a regexp somewhere. >> Unfortunately, I don''t have time to dig in to it myself right now. >> >> I was seeing the same behaviour when I tried hash_including >> (:conditions => [''updated_at <= ?'',Time.now - 1.day]) as part of the >> expectation. > > The problem is a display problem - the Time objects are actually different > by some milliseconds, but you don''t see that in the feedback. > Try this: > now = Time.now > Time.stub!(:now).and_return(now) > Then both calls will return the same object.What David, Aslak & Nick said. btw... ~:$ irb>> Time.now == Time.now=> false Pat
tatyree
2009-Jan-30 09:25 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
Thanks for that everyone! Henceforth I shall always endeavour to stop the flow of time in all of my specs!
Mark Wilden
2009-Jan-30 15:17 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
Avdi Grimm wrote a blog post about why he doesn''t stub Time.now and instead always injects a clock into his objects. I disagreed, but I can''t seem to find the article now. ///ark -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090130/84ac63e3/attachment.html>
David Chelimsky
2009-Jan-30 15:38 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Fri, Jan 30, 2009 at 9:17 AM, Mark Wilden <mark at mwilden.com> wrote:> Avdi Grimm wrote a blog post about why he doesn''t stub Time.now and instead > always injects a clock into his objects. I disagreed, but I can''t seem to > find the article now.http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/297660> > ///ark > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Mark Wilden
2009-Jan-30 17:05 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Fri, Jan 30, 2009 at 7:38 AM, David Chelimsky <dchelimsky at gmail.com>wrote:> On Fri, Jan 30, 2009 at 9:17 AM, Mark Wilden <mark at mwilden.com> wrote: > > Avdi Grimm wrote a blog post about why he doesn''t stub Time.now and > instead > > always injects a clock into his objects. I disagreed, but I can''t seem to > > find the article now. > > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/297660 >Yeah, I saw that, but he laid out his case in greater depth in a blog post (i know because I posted a comment disagreeing with it!). The interesting thing is that Avdi says that stubbing Time.now has broken some of his tests in the past because of other code (like RSpec) that calls it. I can''t say I''ve ever run into that myself, but it bears keeping in mind. ///ark -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090130/a6c854ae/attachment.html>
Pat Maddox
2009-Jan-30 18:00 UTC
[rspec-users] Strange message expectation behaviour with Time.now in a find condition
On Fri, Jan 30, 2009 at 9:05 AM, Mark Wilden <mark at mwilden.com> wrote:> On Fri, Jan 30, 2009 at 7:38 AM, David Chelimsky <dchelimsky at gmail.com> > wrote: >> >> On Fri, Jan 30, 2009 at 9:17 AM, Mark Wilden <mark at mwilden.com> wrote: >> > Avdi Grimm wrote a blog post about why he doesn''t stub Time.now and >> > instead >> > always injects a clock into his objects. I disagreed, but I can''t seem >> > to >> > find the article now. >> >> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/297660 > > Yeah, I saw that, but he laid out his case in greater depth in a blog post > (i know because I posted a comment disagreeing with it!). > > The interesting thing is that Avdi says that stubbing Time.now has broken > some of his tests in the past because of other code (like RSpec) that calls > it. I can''t say I''ve ever run into that myself, but it bears keeping in > mind.I think that using a custom Clock class can be very useful. However, it can cause confusion in Rails apps, because AR uses Time.now for created_at and updated_at. You''d have to keep specific track of when you meant to use Clock and when you wanted to control Time, and to me it''s just not worth it. Pat