drewB
2010-Apr-01 20:14 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
Occasionally, I find myself in a situation where I want to have a mock
obj returned if a method is called with a particular argument but
handled normally otherwise. For example, lets say I have a Model
named User and I am specing a controller that sends messages from one
user to another. When User.find is called for the user who is making
the request I want it to run normally but when User.find is called for
the receiver I want it to return a mocked obj. In this case, I can do
something like (http://gist.github.com/352305):
user = mock_model(User)
User.stub!(:find).at_least(1).and_return do |id|
if id == mock_user.id.to_s
user
else
User.find_by_id(id)
end
end
If I didn''t have another method that allowed me to find a User by
it''s
id this won''t work.
Is there an easier way to accomplish this?
David Chelimsky
2010-Apr-01 20:35 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
On Apr 1, 2010, at 3:14 PM, drewB wrote:> Occasionally, I find myself in a situation where I want to have a mock > obj returned if a method is called with a particular argument but > handled normally otherwise. For example, lets say I have a Model > named User and I am specing a controller that sends messages from one > user to another. When User.find is called for the user who is making > the request I want it to run normally but when User.find is called for > the receiver I want it to return a mocked obj. In this case, I can do > something like (http://gist.github.com/352305): > > user = mock_model(User) > User.stub!(:find).at_least(1).and_return do |id| > if id == mock_user.id.to_s > user > else > User.find_by_id(id) > end > end > > If I didn''t have another method that allowed me to find a User by it''s > id this won''t work. > > Is there an easier way to accomplish this?Not really. When you stub a method, the framework overrides that method with its own implementation. There''s no mechanism in place to say "pass the message onto the real object if it doesn''t have the arguments I''m interested in." I''m not sure of any framework that does that. Maybe RR, but I''m not sure. Good luck. David
Matt Wynne
2010-Apr-01 20:45 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
On 1 Apr 2010, at 21:35, David Chelimsky wrote:> On Apr 1, 2010, at 3:14 PM, drewB wrote: > >> Occasionally, I find myself in a situation where I want to have a >> mock >> obj returned if a method is called with a particular argument but >> handled normally otherwise. For example, lets say I have a Model >> named User and I am specing a controller that sends messages from one >> user to another. When User.find is called for the user who is making >> the request I want it to run normally but when User.find is called >> for >> the receiver I want it to return a mocked obj. In this case, I can >> do >> something like (http://gist.github.com/352305): >> >> user = mock_model(User) >> User.stub!(:find).at_least(1).and_return do |id| >> if id == mock_user.id.to_s >> user >> else >> User.find_by_id(id) >> end >> end >> >> If I didn''t have another method that allowed me to find a User by >> it''s >> id this won''t work. >> >> Is there an easier way to accomplish this? > > Not really. When you stub a method, the framework overrides that > method with its own implementation. There''s no mechanism in place to > say "pass the message onto the real object if it doesn''t have the > arguments I''m interested in." I''m not sure of any framework that > does that. Maybe RR, but I''m not sure. > > Good luck. > DavidI can''t help but chime in here that I would be pretty irritated to come across a test that mixed up using mocks and real objects, especially when they''re the same class. Can you not use a mock for the other instance of User too?> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-userscheers, Matt http://mattwynne.net +447974 430184
drewB
2010-Apr-01 22:12 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
David, thanks for your response. Matt, I totally hear you. In this contrived example, you probably could but in the project I am working on it would be very difficult. One of the challenges of joining a project already in progress... On Apr 1, 1:45?pm, Matt Wynne <m... at mattwynne.net> wrote:> On 1 Apr 2010, at 21:35, David Chelimsky wrote: > > > > > On Apr 1, 2010, at 3:14 PM, drewB wrote: > > >> Occasionally, I find myself in a situation where I want to have a ? > >> mock > >> obj returned if a method is called with a particular argument but > >> handled normally otherwise. ?For example, lets say I have a Model > >> named User and I am specing a controller that sends messages from one > >> user to another. ?When User.find is called for the user who is making > >> the request I want it to run normally but when User.find is called ? > >> for > >> the receiver I want it to return a mocked obj. ?In this case, I can ? > >> do > >> something like (http://gist.github.com/352305): > > >> user = mock_model(User) > >> User.stub!(:find).at_least(1).and_return do |id| > >> ? if id == mock_user.id.to_s > >> ? ? user > >> ? else > >> ? ? User.find_by_id(id) > >> ? end > >> end > > >> If I didn''t have another method that allowed me to find a User by ? > >> it''s > >> id this won''t work. > > >> Is there an easier way to accomplish this? > > > Not really. When you stub a method, the framework overrides that ? > > method with its own implementation. There''s no mechanism in place to ? > > say "pass the message onto the real object if it doesn''t have the ? > > arguments I''m interested in." I''m not sure of any framework that ? > > does that. Maybe RR, but I''m not sure. > > > Good luck. > > David > > I can''t help but chime in here that I would be pretty irritated to ? > come across a test that mixed up using mocks and real objects, ? > especially when they''re the same class. Can you not use a mock for the ? > other instance of User too? > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-us... at rubyforge.org > >http://rubyforge.org/mailman/listinfo/rspec-users > > cheers, > Matt > > http://mattwynne.net > +447974 430184 > > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
drewB
2010-Apr-01 22:29 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
For anyone who might come across this message looking for a solution
to the same problem, I wrote the following function to take care of it
(http://gist.github.com/352449)
def stub_find_for_specific_values(model, stubs)
model.stub!(:find).at_least(1).and_return do |id|
if stubs.has_key? id
stubs[id]
else
model.find_by_id(id)
end
end
end
#example below will return the mock_user if its id is search for
otherwise find will search as normal
mock_user = mock_model(User)
stub_find_for_specific_values(User, mock_user.id => mock_user)
On Apr 1, 3:12?pm, drewB <dbats... at gmail.com>
wrote:> David, thanks for your response.
>
> Matt, I totally hear you. ?In this contrived example, you probably
> could but in the project I am working on it would be very difficult.
> One of the challenges of joining a project already in progress...
>
> On Apr 1, 1:45?pm, Matt Wynne <m... at mattwynne.net> wrote:
>
> > On 1 Apr 2010, at 21:35, David Chelimsky wrote:
>
> > > On Apr 1, 2010, at 3:14 PM, drewB wrote:
>
> > >> Occasionally, I find myself in a situation where I want to
have a ?
> > >> mock
> > >> obj returned if a method is called with a particular argument
but
> > >> handled normally otherwise. ?For example, lets say I have a
Model
> > >> named User and I am specing a controller that sends messages
from one
> > >> user to another. ?When User.find is called for the user who
is making
> > >> the request I want it to run normally but when User.find is
called ?
> > >> for
> > >> the receiver I want it to return a mocked obj. ?In this case,
I can ?
> > >> do
> > >> something like (http://gist.github.com/352305):
>
> > >> user = mock_model(User)
> > >> User.stub!(:find).at_least(1).and_return do |id|
> > >> ? if id == mock_user.id.to_s
> > >> ? ? user
> > >> ? else
> > >> ? ? User.find_by_id(id)
> > >> ? end
> > >> end
>
> > >> If I didn''t have another method that allowed me to
find a User by ?
> > >> it''s
> > >> id this won''t work.
>
> > >> Is there an easier way to accomplish this?
>
> > > Not really. When you stub a method, the framework overrides that
?
> > > method with its own implementation. There''s no mechanism
in place to ?
> > > say "pass the message onto the real object if it
doesn''t have the ?
> > > arguments I''m interested in." I''m not sure
of any framework that ?
> > > does that. Maybe RR, but I''m not sure.
>
> > > Good luck.
> > > David
>
> > I can''t help but chime in here that I would be pretty
irritated to ?
> > come across a test that mixed up using mocks and real objects, ?
> > especially when they''re the same class. Can you not use a
mock for the ?
> > other instance of User too?
>
> > > _______________________________________________
> > > rspec-users mailing list
> > > rspec-us... at rubyforge.org
> > >http://rubyforge.org/mailman/listinfo/rspec-users
>
> > cheers,
> > Matt
>
> >http://mattwynne.net
> > +447974 430184
>
> > _______________________________________________
> > rspec-users mailing list
> > rspec-us... at
rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
>
> _______________________________________________
> rspec-users mailing list
> rspec-us... at
rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
Matt Wynne
2010-Apr-02 00:35 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
On 1 Apr 2010, at 23:12, drewB wrote:> David, thanks for your response. > > Matt, I totally hear you. In this contrived example, you probably > could but in the project I am working on it would be very difficult. > One of the challenges of joining a project already in progress...I have felt that pain many times :) This book is a great read when you''re working with other people''s crap: http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052> > On Apr 1, 1:45 pm, Matt Wynne <m... at mattwynne.net> wrote: >> On 1 Apr 2010, at 21:35, David Chelimsky wrote: >> >> >> >>> On Apr 1, 2010, at 3:14 PM, drewB wrote: >> >>>> Occasionally, I find myself in a situation where I want to have a >>>> mock >>>> obj returned if a method is called with a particular argument but >>>> handled normally otherwise. For example, lets say I have a Model >>>> named User and I am specing a controller that sends messages from >>>> one >>>> user to another. When User.find is called for the user who is >>>> making >>>> the request I want it to run normally but when User.find is called >>>> for >>>> the receiver I want it to return a mocked obj. In this case, I can >>>> do >>>> something like (http://gist.github.com/352305): >> >>>> user = mock_model(User) >>>> User.stub!(:find).at_least(1).and_return do |id| >>>> if id == mock_user.id.to_s >>>> user >>>> else >>>> User.find_by_id(id) >>>> end >>>> end >> >>>> If I didn''t have another method that allowed me to find a User by >>>> it''s >>>> id this won''t work. >> >>>> Is there an easier way to accomplish this? >> >>> Not really. When you stub a method, the framework overrides that >>> method with its own implementation. There''s no mechanism in place to >>> say "pass the message onto the real object if it doesn''t have the >>> arguments I''m interested in." I''m not sure of any framework that >>> does that. Maybe RR, but I''m not sure. >> >>> Good luck. >>> David >> >> I can''t help but chime in here that I would be pretty irritated to >> come across a test that mixed up using mocks and real objects, >> especially when they''re the same class. Can you not use a mock for >> the >> other instance of User too? >> >> >> >>> _______________________________________________ >>> rspec-users mailing list >>> rspec-us... at rubyforge.org >>> http://rubyforge.org/mailman/listinfo/rspec-users >> >> cheers, >> Matt >> >> http://mattwynne.net >> +447974 430184 >> >> _______________________________________________ >> rspec-users mailing list >> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-userscheers, Matt http://mattwynne.net +447974 430184
Brian Takita
2010-Apr-02 01:28 UTC
[rspec-users] setting partial stub for just one value and letting obj handle the rest
I used to do the following when I used rspec mocks.
user = mock_model(User)
find_method = User.method(:find)
User.stub!(:find).at_least(1).and_return do |id|
if id == mock_user.id.to_s
user
else
find_method.call(id) # May need to instance_eval here, but I
think .call is sufficient.
end
end
In fact this sort of inspired me to mock.proxy method call. Of course YMMV :-)
On Thu, Apr 1, 2010 at 3:29 PM, drewB <dbatshaw at gmail.com>
wrote:> For anyone who might come across this message looking for a solution
> to the same problem, I wrote the following function to take care of it
> (http://gist.github.com/352449)
>
> def stub_find_for_specific_values(model, stubs)
> ?model.stub!(:find).at_least(1).and_return do |id|
> ? ?if stubs.has_key? id
> ? ? ?stubs[id]
> ? ?else
> ? ? ?model.find_by_id(id)
> ? ?end
> ?end
> end
>
> #example below will return the mock_user if its id is search for
> otherwise find will search as normal
> mock_user = mock_model(User)
> stub_find_for_specific_values(User, mock_user.id => mock_user)
>
> On Apr 1, 3:12?pm, drewB <dbats... at gmail.com> wrote:
>> David, thanks for your response.
>>
>> Matt, I totally hear you. ?In this contrived example, you probably
>> could but in the project I am working on it would be very difficult.
>> One of the challenges of joining a project already in progress...
>>
>> On Apr 1, 1:45?pm, Matt Wynne <m... at mattwynne.net> wrote:
>>
>> > On 1 Apr 2010, at 21:35, David Chelimsky wrote:
>>
>> > > On Apr 1, 2010, at 3:14 PM, drewB wrote:
>>
>> > >> Occasionally, I find myself in a situation where I want
to have a
>> > >> mock
>> > >> obj returned if a method is called with a particular
argument but
>> > >> handled normally otherwise. ?For example, lets say I have
a Model
>> > >> named User and I am specing a controller that sends
messages from one
>> > >> user to another. ?When User.find is called for the user
who is making
>> > >> the request I want it to run normally but when User.find
is called
>> > >> for
>> > >> the receiver I want it to return a mocked obj. ?In this
case, I can
>> > >> do
>> > >> something like (http://gist.github.com/352305):
>>
>> > >> user = mock_model(User)
>> > >> User.stub!(:find).at_least(1).and_return do |id|
>> > >> ? if id == mock_user.id.to_s
>> > >> ? ? user
>> > >> ? else
>> > >> ? ? User.find_by_id(id)
>> > >> ? end
>> > >> end
>>
>> > >> If I didn''t have another method that allowed me
to find a User by
>> > >> it''s
>> > >> id this won''t work.
>>
>> > >> Is there an easier way to accomplish this?
>>
>> > > Not really. When you stub a method, the framework overrides
that
>> > > method with its own implementation. There''s no
mechanism in place to
>> > > say "pass the message onto the real object if it
doesn''t have the
>> > > arguments I''m interested in." I''m not
sure of any framework that
>> > > does that. Maybe RR, but I''m not sure.
>>
>> > > Good luck.
>> > > David
>>
>> > I can''t help but chime in here that I would be pretty
irritated to
>> > come across a test that mixed up using mocks and real objects,
>> > especially when they''re the same class. Can you not use a
mock for the
>> > other instance of User too?
>>
>> > > _______________________________________________
>> > > rspec-users mailing list
>> > > rspec-us... at rubyforge.org
>> > >http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> > cheers,
>> > Matt
>>
>> >http://mattwynne.net
>> > +447974 430184
>>
>> > _______________________________________________
>> > rspec-users mailing list
>> > rspec-us... at
rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-us... at
rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>