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 >