Forum: RSpec Stubbing times: #from_now et al.

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (Guest)
on 2008-11-05 19:55
(Received via mailing list)
I had a look around for how to stub Time.now , #from_now , etc, and
came across this, which was useful:
http://devblog.michaelgalero.com/2007/11/23/action...

Unfortunately, my situation is slightly different, and causes that
solution to not be applicable. This is what I'm trying to spec:

def remember_me_for(time)
   remember_me_until time.from_now.utc
end

I thought this would work:

it 'should remember a user for a period of time' do
   user          = create_user
   one_week      = 1.week
   from_now      = 1.week.from_now
   from_now_utc  = 1.week.from_now.utc

   one_week.stub!(:from_now).and_return from_now
   from_now.stub!(:utc).and_return from_now_utc

   user.should_receive(:remember_me_until).with from_now_utc

   user.remember_me_for one_week
end

But that fails, referencing the stub on "one_week":

TypeError in 'User should remember a user for a period of time'
no virtual class for Fixnum

Any suggestions for how to solve this? Thanks!
Nick
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-11-05 20:44
(Received via mailing list)
On Wed, Nov 5, 2008 at 12:51 PM, Nick Hoffman <nick@deadorange.com>
wrote:
>
>
> Any suggestions for how to solve this? Thanks!
Looks like you can't stub anything on a Fixnum because of the way
RSpec's mocking works.

>> require 'spec/mocks'
=> true
>> 1.stub!(:foo)
TypeError: no virtual class for Fixnum

Same with mocha, apparently.

>> require 'mocha'
=> true
>> 1.stubs(:foo)
TypeError: no virtual class for Fixnum

Same with rr:

>> require 'rr'
=> true
>> mock(1).foo
TypeError: no virtual class for Fixnum

And lastly (but not leastly), flexmock:

>> require 'flexmock'
>> include FlexMock::MockContainer
=> Object
>> flexmock(1).foo
TypeError: no virtual class for Fixnum


The problem is there is no Singleton Class for 1, probably an
efficiency in Ruby since 1 is, itself, a Singleton.

All of these frameworks try to manipulate methods on the object's
singleton class. So no mocking/stubbing on Fixnums. Apparently.

Not much help - sorry.

David
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (Guest)
on 2008-11-05 21:02
(Received via mailing list)
On 2008-11-05, at 14:42, David Chelimsky wrote:
> The problem is there is no Singleton Class for 1, probably an
> efficiency in Ruby since 1 is, itself, a Singleton.
>
> All of these frameworks try to manipulate methods on the object's
> singleton class. So no mocking/stubbing on Fixnums. Apparently.
>
> Not much help - sorry.

That was a good explanation. Thanks, mate. At least now I know not to
chase this path any further!
C694a032be7518a0d704318895f8fe1d?d=identicon&s=25 Ben Mabey (mabes)
on 2008-11-05 21:04
(Received via mailing list)
Nick Hoffman wrote:
> end
>   from_now.stub!(:utc).and_return from_now_utc
>
> Any suggestions for how to solve this? Thanks!
> Nick
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users


Hey Nick,
It is generally a bad idea to stub/mock a method on the object you are
verifying the behaviour of. I would recommend a state-based approach of
testing this method as opposed to the interaction-based one you are
pursuing.  The reason being is that you want to verify the behaviour of
the object as a whole.  How the object uses it's internal methods and
state is none of the code example's business.  Without knowing the other
methods on User I don't know the best way to verify the behavior.. What
other methods that deal with the remember functionality are part of the
public API?  Assuming it is an AR model and you have a
'remember_me_until' column you could do something like:


it 'should remember a user for a period of time' do
  user          = create_user

  user.remember_me_for(1.week)

  user.remember_me_until.should == 1.week.from_now.utc
end

Again, using the #remember_me_until method is testing the internal state
of the object but without knowing your other methods I don't what the
better options (if any) are.

HTH,
Ben
48641c4be1fbe167929fb16c9fd94990?d=identicon&s=25 Mark Wilden (Guest)
on 2008-11-05 21:15
(Received via mailing list)
On Wed, Nov 5, 2008 at 11:42 AM, David Chelimsky
<dchelimsky@gmail.com>wrote:


> Looks like you can't stub anything on a Fixnum because of the way
> RSpec's mocking works.
>
> >> require 'spec/mocks'
> => true
> >> 1.stub!(:foo)
> TypeError: no virtual class for Fixnum
>

What I can't figure out is this:

>> 1.day
=> 1 day

>> 1.day.class
=> Fixnum

Is 1.day an ActiveSupport::Duration or a Fixnum?

///ark
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (Guest)
on 2008-11-05 21:17
(Received via mailing list)
On 2008-11-05, at 15:02, Ben Mabey wrote:
> an AR model and you have a 'remember_me_until' column you could do
> state of the object but without knowing your other methods I don't
> what the better options (if any) are.
>
> HTH,
> Ben

Hi Ben. #remember_me is used to keep a user logged in to the website
if they ticked the "Remember me?" checkbox in the login form. It's
only called from one location in the app:

case
     when valid_remember_cookie? then @current_user.refresh_token #
keeping same expiry date
     when new_cookie_flag        then @current_user.remember_me
     else                             @current_user.forget_me
end

So as you suggested, my spec example should probably just be checking
to see that the User instance's "remember_me_until" attribute is set
to an appropriate value.

Thanks!
Nick
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (Guest)
on 2008-11-05 21:33
(Received via mailing list)
On 2008-11-05, at 15:10, Mark Wilden wrote:
> ///ark
It's an ActiveSupport::Duration :

  48         def days
  49           ActiveSupport::Duration.new(self * 24.hours, [[:days,
self]])
  50         end
  51         alias :day :days

I've no idea why 1.day.class returns Fixnum though..
48641c4be1fbe167929fb16c9fd94990?d=identicon&s=25 Mark Wilden (Guest)
on 2008-11-05 21:41
(Received via mailing list)
On Wed, Nov 5, 2008 at 12:26 PM, Nick Hoffman <nick@deadorange.com>
wrote:

>> I've no idea why 1.day.class returns Fixnum though..
>

Yeah, I'd looked at the code. Why #class returns Fixnum was my question,
actually. Something to do with coercion, maybe.

The other thing is that if it were simply a Duration, I'd expect you to
be
able to stub it.

///ark
This topic is locked and can not be replied to.