I am setting up an AR mock object and wanted to sanity check it. My intent is to mix this into all my examples and then override/add methods where necessary. Note that I''ve anticipated three cases for find: find with one numeric argument => object find with :all => Array find with anything else => nil This roughly approximates how ActiveRecord::find works in this case (neglecting the optional parameters). My question is: Is this calculation of the return value a bad thing, and if so, how better to accomplish it? Thanks --------- module SettingsMock def setup_mock @countable = mock(''countable'') @countable.stub!(:count).and_return(1) @countable.stub!(:full_messages).and_return([''a message'']) @setting = mock_model Setting do |m| m.stub!(:save).and_return(true) m.stub!(:destroy) m.stub!(:errors).and_return(@countable) m.stub!(:setting_name).and_return(''first_name'') m.stub!(:setting_value).and_return(''first_value'') m.stub!(:setting_type).and_return(''first_type'') end Setting.should_receive(:find).any_number_of_times.and_return do |a| case a when :all then [@setting, @setting] when /\d+/ then @setting else nil end end end end
On 4/30/07, s.ross <cwdinfo at gmail.com> wrote:> I am setting up an AR mock object and wanted to sanity check it. My > intent is to mix this into all my examples and then override/add > methods where necessary. Note that I''ve anticipated three cases for > find: > > find with one numeric argument => object > find with :all => Array > find with anything else => nil > > This roughly approximates how ActiveRecord::find works in this case > (neglecting the optional parameters). > > My question is: Is this calculation of the return value a bad thing,Well, it will make failures more difficult to understand. In my book, that is a very bad thing.> and if so, how better to accomplish it?How about parameterizing setup_mock or coming up w/ 3 separate methods to create the mocks that are supposed to behave 3 different ways? Cheers, David> > Thanks > > --------- > > module SettingsMock > def setup_mock > @countable = mock(''countable'') > @countable.stub!(:count).and_return(1) > @countable.stub!(:full_messages).and_return([''a message'']) > @setting = mock_model Setting do |m| > m.stub!(:save).and_return(true) > m.stub!(:destroy) > m.stub!(:errors).and_return(@countable) > m.stub!(:setting_name).and_return(''first_name'') > m.stub!(:setting_value).and_return(''first_value'') > m.stub!(:setting_type).and_return(''first_type'') > end > Setting.should_receive(:find).any_number_of_times.and_return do |a| > case a > when :all then [@setting, @setting] > when /\d+/ then @setting > else > nil > end > end > end > end > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Yes, I was afraid that might be the answer. Here''s the problem. I have specs that say: describe "The Settings edit/update sequence" do it "should succeed with POST and good data" it "should fail with POST and bad data" it "should fail with POST and bad ID" end The controller case I am trying to capture is that if it does a find (1) everything is hunky-dory. For the second case, I stub save to return false. The third one is the problematic one. In this case, a bogus ID comes in, and the stub should return nil but *then* then controller will do a find(:all) and needs an array (all in the same example). As you can see, I''ve handled it by examining the parameters. What would be a better approach? Thanks On Apr 30, 2007, at 1:37 PM, David Chelimsky wrote:> On 4/30/07, s.ross <cwdinfo at gmail.com> wrote: >> I am setting up an AR mock object and wanted to sanity check it. My >> intent is to mix this into all my examples and then override/add >> methods where necessary. Note that I''ve anticipated three cases for >> find: >> >> find with one numeric argument => object >> find with :all => Array >> find with anything else => nil >> >> This roughly approximates how ActiveRecord::find works in this case >> (neglecting the optional parameters). >> >> My question is: Is this calculation of the return value a bad thing, > > Well, it will make failures more difficult to understand. In my book, > that is a very bad thing. > >> and if so, how better to accomplish it? > > How about parameterizing setup_mock or coming up w/ 3 separate methods > to create the mocks that are supposed to behave 3 different ways? > > Cheers, > David > >> >> Thanks >> >> --------- >> >> module SettingsMock >> def setup_mock >> @countable = mock(''countable'') >> @countable.stub!(:count).and_return(1) >> @countable.stub!(:full_messages).and_return([''a message'']) >> @setting = mock_model Setting do |m| >> m.stub!(:save).and_return(true) >> m.stub!(:destroy) >> m.stub!(:errors).and_return(@countable) >> m.stub!(:setting_name).and_return(''first_name'') >> m.stub!(:setting_value).and_return(''first_value'') >> m.stub!(:setting_type).and_return(''first_type'') >> end >> Setting.should_receive(:find).any_number_of_times.and_return >> do |a| >> case a >> when :all then [@setting, @setting] >> when /\d+/ then @setting >> else >> nil >> end >> end >> end >> end >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On 4/30/07, s.ross <cwdinfo at gmail.com> wrote:> > Yes, I was afraid that might be the answer. Here''s the problem. I > have specs that say: > > describe "The Settings edit/update sequence" do > it "should succeed with POST and good data" > it "should fail with POST and bad data" > it "should fail with POST and bad ID" > endI don''t know if it''s right or wrong, but my controller tests have different contexts for each one of those situations. ie: context "POST /foo/blah with invalid :xyz param" I think in some cases where I know find is being called multiple times, I build an array of items, and then do: Object.stub!(:find).and_return(*@items) But that doesn''t sound like it would help you. What about: Setting.should_receive(:find).with(:all).any_number_of_times.and_return([@setting, @setting]) Setting.should_receive (:find).with(1).any_number_of_times.and_return(@setting) Don''t think I''ve tried that before. -james -- James A. Hillyerd <james at hillyerd.com> Chief Technical Officer - ActiveRain Corp -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/rspec-users/attachments/20070430/bb8e7210/attachment.html
This would be cool if it worked, but it seems not to. I think there may be a "last one wins" behavior to class method mocking. Any other thoughts? Thanks On Apr 30, 2007, at 2:11 PM, James Hillyerd wrote:> But that doesn''t sound like it would help you. What about: > > Setting.should_receive(:find).with > (:all).any_number_of_times.and_return([@setting, @setting]) > Setting.should_receive(:find).with(1).any_number_of_times.and_return > (@setting)-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/rspec-users/attachments/20070430/913348e3/attachment.html