Sven Fuchs
2008-Jul-13 13:49 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
I''ve been wondering how to expect arbitrary methods being called in a particular order. The RSpec documentation for expecting method calls on mock objects mentions that it is possible to pass a block to #should_receive, but does not mention that it can be used to track the method call order pretty easily: http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec Is there a better way of doing this? If not, do you think it would make sense to add this to the RSpec docs? http://rspec.info/documentation/mocks/message_expectations.html -- sven fuchs svenfuchs at artweb-design.de artweb design http://www.artweb-design.de gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)
Pat Maddox
2008-Jul-13 14:32 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de> wrote:> I''ve been wondering how to expect arbitrary methods being called in a > particular order. The RSpec documentation for expecting method calls on mock > objects mentions that it is possible to pass a block to #should_receive, but > does not mention that it can be used to track the method call order pretty > easily: > > http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec > > Is there a better way of doing this? > > If not, do you think it would make sense to add this to the RSpec docs? > http://rspec.info/documentation/mocks/message_expectations.htmlHey Sven, Mock objects have an optional notion of ordering. Check out the following spec: describe "a mock object" do it "should expect ordered messages" do foo = mock("ordered mock") foo.should_receive(:first).ordered foo.should_receive(:second).ordered foo.should_receive(:third).ordered foo.first foo.second foo.third end end Changing the order in which they''re called will raise an ExpectationNotMetError. Pat
David Chelimsky
2008-Jul-13 14:41 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On Sun, Jul 13, 2008 at 9:32 AM, Pat Maddox <pergesu at gmail.com> wrote:> On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de> wrote: >> I''ve been wondering how to expect arbitrary methods being called in a >> particular order. The RSpec documentation for expecting method calls on mock >> objects mentions that it is possible to pass a block to #should_receive, but >> does not mention that it can be used to track the method call order pretty >> easily: >> >> http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec >> >> Is there a better way of doing this? >> >> If not, do you think it would make sense to add this to the RSpec docs? >> http://rspec.info/documentation/mocks/message_expectations.html > > Hey Sven, > > Mock objects have an optional notion of ordering. Check out the following spec: > > describe "a mock object" do > it "should expect ordered messages" do > foo = mock("ordered mock") > foo.should_receive(:first).ordered > foo.should_receive(:second).ordered > foo.should_receive(:third).ordered > > foo.first > foo.second > foo.third > end > end > > Changing the order in which they''re called will raise an ExpectationNotMetError.Sven, FYI - this is explained on the page you mentioned: http://rspec.info/documentation/mocks/message_expectations.html Cheers, David> > Pat > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Sven Fuchs
2008-Jul-13 15:01 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On 13.07.2008, at 16:41, David Chelimsky wrote:> On Sun, Jul 13, 2008 at 9:32 AM, Pat Maddox <pergesu at gmail.com> wrote: >> On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de >> > wrote: >>> I''ve been wondering how to expect arbitrary methods being called >>> in a >>> particular order. The RSpec documentation for expecting method >>> calls on mock >>> objects mentions that it is possible to pass a block to >>> #should_receive, but >>> does not mention that it can be used to track the method call >>> order pretty >>> easily: >>> >>> http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec >>> >>> Is there a better way of doing this? >>> >>> If not, do you think it would make sense to add this to the RSpec >>> docs? >>> http://rspec.info/documentation/mocks/message_expectations.html >> >> Hey Sven, >> >> Mock objects have an optional notion of ordering. Check out the >> following spec: >> >> describe "a mock object" do >> it "should expect ordered messages" do >> foo = mock("ordered mock") >> foo.should_receive(:first).ordered >> foo.should_receive(:second).ordered >> foo.should_receive(:third).ordered >> >> foo.first >> foo.second >> foo.third >> end >> end >> >> Changing the order in which they''re called will raise an >> ExpectationNotMetError. > > Sven, FYI - this is explained on the page you mentioned: > http://rspec.info/documentation/mocks/message_expectations.htmlHey guys, thanks for the quick answers :) Maybe I was not clear enough about what I wanted to spec. Or I actually do not understand what #ordered does. In Pat''s spec above the methods #first, #second and #third are called on the same object foo and the spec defines the order. That''s kind of the opposite of my usecase. I wanted to specify that the a method #run (or whatever) is called on *different* objects in a particular order. Like: filter_1 = mock(''filter_1'') filter_2 = mock(''filter_2'') filter_chain << filter_1 filter_chain << filter_2 Now, when the filter_chain is run I want to expect that the filters are run in the order they were added to the chain: filter_chain.run methods_called_on_individual_filters.should == [''filter_1#run'', ''filter_2#run''] # pseudo-code If that''s possible somehow with should_receive(:run).ordered than at least it''s not very clear from that docs page which only talks about expecting the order of methods being called on the same mock, not on different mocks. ("There are times when you want to specify the order of messages sent to *a* mock") Am I missing something? -- sven fuchs svenfuchs at artweb-design.de artweb design http://www.artweb-design.de gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)
Sven Fuchs
2008-Jul-13 15:35 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On 13.07.2008, at 17:01, Sven Fuchs wrote:> > On 13.07.2008, at 16:41, David Chelimsky wrote: > >> On Sun, Jul 13, 2008 at 9:32 AM, Pat Maddox <pergesu at gmail.com> >> wrote: >>> On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de >>> > wrote: >>>> I''ve been wondering how to expect arbitrary methods being called >>>> in a >>>> particular order. The RSpec documentation for expecting method >>>> calls on mock >>>> objects mentions that it is possible to pass a block to >>>> #should_receive, but >>>> does not mention that it can be used to track the method call >>>> order pretty >>>> easily: >>>> >>>> http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec >>>> >>>> Is there a better way of doing this? >>>> >>>> If not, do you think it would make sense to add this to the RSpec >>>> docs? >>>> http://rspec.info/documentation/mocks/message_expectations.html >>> >>> Hey Sven, >>> >>> Mock objects have an optional notion of ordering. Check out the >>> following spec: >>> >>> describe "a mock object" do >>> it "should expect ordered messages" do >>> foo = mock("ordered mock") >>> foo.should_receive(:first).ordered >>> foo.should_receive(:second).ordered >>> foo.should_receive(:third).ordered >>> >>> foo.first >>> foo.second >>> foo.third >>> end >>> end >>> >>> Changing the order in which they''re called will raise an >>> ExpectationNotMetError. >> >> Sven, FYI - this is explained on the page you mentioned: >> http://rspec.info/documentation/mocks/message_expectations.html > > Hey guys, thanks for the quick answers :) > > Maybe I was not clear enough about what I wanted to spec. Or I > actually do not understand what #ordered does. > > In Pat''s spec above the methods #first, #second and #third are > called on the same object foo and the spec defines the order. That''s > kind of the opposite of my usecase. I wanted to specify that the a > method #run (or whatever) is called on *different* objects in a > particular order. Like: > > filter_1 = mock(''filter_1'') > filter_2 = mock(''filter_2'') > filter_chain << filter_1 > filter_chain << filter_2 > > Now, when the filter_chain is run I want to expect that the filters > are run in the order they were added to the chain: > > filter_chain.run > methods_called_on_individual_filters.should == [''filter_1#run'', > ''filter_2#run''] # pseudo-code > > If that''s possible somehow with should_receive(:run).ordered than at > least it''s not very clear from that docs page which only talks about > expecting the order of methods being called on the same mock, not on > different mocks. ("There are times when you want to specify the > order of messages sent to *a* mock") > > Am I missing something?Maybe it''s bit more clear this way: class Chain < Array def run each{|object| object.run} end end describe "Expecting the order of methods being called on arbitrary objects" do it "works" do first = mock(''first'') second = mock(''second'') chain = Chain.new chain << first chain << second second.should_receive(:run).ordered first.should_receive(:run).ordered chain.run end end This passes, of course. I''d want to to specify that first#run is run first and second#run is run second though and I think I can''t do that with should_receive.ordered -- sven fuchs svenfuchs at artweb-design.de artweb design http://www.artweb-design.de gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)
Ashley Moran
2008-Jul-13 15:44 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On Jul 13, 2008, at 4:35 pm, Sven Fuchs wrote:> describe "Expecting the order of methods being called on arbitrary > objects" do > it "works" do > first = mock(''first'') > second = mock(''second'') > > chain = Chain.new > chain << first > chain << second > > second.should_receive(:run).ordered > first.should_receive(:run).ordered > chain.run > end > endHi Sven I think you want second.should_receive(:run) do first.should_receive(:run) end which, if Mail.app is running my specs correctly, should only pass if second receives :run before first Is that what you were after? Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/
Zach Dennis
2008-Jul-13 15:59 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
You want cross mock ordering! I''ve wanted this in RSpec in the past as well. The only ruby-based mocking library I know of that does this is Hardmock. It looks like its RDoc now has instructions for it to work with RSpec: http://hardmock.rubyforge.org/ Zach On Sun, Jul 13, 2008 at 11:35 AM, Sven Fuchs <svenfuchs at artweb-design.de> wrote:> On 13.07.2008, at 17:01, Sven Fuchs wrote: > >> >> On 13.07.2008, at 16:41, David Chelimsky wrote: >> >> On Sun, Jul 13, 2008 at 9:32 AM, Pat Maddox <pergesu at gmail.com> wrote: >>> >>>> On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de> >>>> wrote: >>>> >>>>> I''ve been wondering how to expect arbitrary methods being called in a >>>>> particular order. The RSpec documentation for expecting method calls on >>>>> mock >>>>> objects mentions that it is possible to pass a block to >>>>> #should_receive, but >>>>> does not mention that it can be used to track the method call order >>>>> pretty >>>>> easily: >>>>> >>>>> >>>>> http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec >>>>> >>>>> Is there a better way of doing this? >>>>> >>>>> If not, do you think it would make sense to add this to the RSpec docs? >>>>> http://rspec.info/documentation/mocks/message_expectations.html >>>>> >>>> >>>> Hey Sven, >>>> >>>> Mock objects have an optional notion of ordering. Check out the >>>> following spec: >>>> >>>> describe "a mock object" do >>>> it "should expect ordered messages" do >>>> foo = mock("ordered mock") >>>> foo.should_receive(:first).ordered >>>> foo.should_receive(:second).ordered >>>> foo.should_receive(:third).ordered >>>> >>>> foo.first >>>> foo.second >>>> foo.third >>>> end >>>> end >>>> >>>> Changing the order in which they''re called will raise an >>>> ExpectationNotMetError. >>>> >>> >>> Sven, FYI - this is explained on the page you mentioned: >>> http://rspec.info/documentation/mocks/message_expectations.html >>> >> >> Hey guys, thanks for the quick answers :) >> >> Maybe I was not clear enough about what I wanted to spec. Or I actually do >> not understand what #ordered does. >> >> In Pat''s spec above the methods #first, #second and #third are called on >> the same object foo and the spec defines the order. That''s kind of the >> opposite of my usecase. I wanted to specify that the a method #run (or >> whatever) is called on *different* objects in a particular order. Like: >> >> filter_1 = mock(''filter_1'') >> filter_2 = mock(''filter_2'') >> filter_chain << filter_1 >> filter_chain << filter_2 >> >> Now, when the filter_chain is run I want to expect that the filters are >> run in the order they were added to the chain: >> >> filter_chain.run >> methods_called_on_individual_filters.should == [''filter_1#run'', >> ''filter_2#run''] # pseudo-code >> >> If that''s possible somehow with should_receive(:run).ordered than at least >> it''s not very clear from that docs page which only talks about expecting the >> order of methods being called on the same mock, not on different mocks. >> ("There are times when you want to specify the order of messages sent to *a* >> mock") >> >> Am I missing something? >> > > Maybe it''s bit more clear this way: > > class Chain < Array > def run > each{|object| object.run} > end > end > > describe "Expecting the order of methods being called on arbitrary objects" > do > it "works" do > first = mock(''first'') > second = mock(''second'') > > chain = Chain.new > chain << first > chain << second > > second.should_receive(:run).ordered > first.should_receive(:run).ordered > chain.run > end > end > > This passes, of course. > > I''d want to to specify that first#run is run first and second#run is run > second though and I think I can''t do that with should_receive.ordered > > > > -- > sven fuchs svenfuchs at artweb-design.de > artweb design http://www.artweb-design.de > gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) > d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile) > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Zach Dennis http://www.continuousthinking.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20080713/c4b866e5/attachment-0001.html>
Sven Fuchs
2008-Jul-13 16:03 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
Hey Ashley! How''s things? :) On 13.07.2008, at 17:44, Ashley Moran wrote:> I think you want > > second.should_receive(:run) do > first.should_receive(:run) > end > > which, if Mail.app is running my specs correctly, should only pass > if second receives :run before first > > Is that what you were after?Wow, yes. This also uses the block passed to should_receive, but in a nicer way than my inital attemp which is a bit chatty. It''d look a bit odd when I want to specify the order for a bunch of methods, but actually I don''t need to do that here. Again, this really should be documented. I even started digging into the RSpec source, but obviously lacked the creativity for this :) -- sven fuchs svenfuchs at artweb-design.de artweb design http://www.artweb-design.de gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)
Sven Fuchs
2008-Jul-13 16:04 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
Hi Zach, On 13.07.2008, at 17:59, Zach Dennis wrote:> You want cross mock ordering! I''ve wanted this in RSpec in the past > as well. The only ruby-based mocking library I know of that does > this is Hardmock. It looks like its RDoc now has instructions for it > to work with RSpec: > > http://hardmock.rubyforge.org/Thanks for the suggestion! To be honest, I''m not eager to add another library. Ashley''s approach seems to work fine and I only need it in a couple of specs.> > > Zach > > On Sun, Jul 13, 2008 at 11:35 AM, Sven Fuchs <svenfuchs at artweb-design.de > > wrote: > On 13.07.2008, at 17:01, Sven Fuchs wrote: > > On 13.07.2008, at 16:41, David Chelimsky wrote: > > On Sun, Jul 13, 2008 at 9:32 AM, Pat Maddox <pergesu at gmail.com> wrote: > On Sun, Jul 13, 2008 at 9:49 AM, Sven Fuchs <svenfuchs at artweb-design.de > > wrote: > I''ve been wondering how to expect arbitrary methods being called in a > particular order. The RSpec documentation for expecting method calls > on mock > objects mentions that it is possible to pass a block to > #should_receive, but > does not mention that it can be used to track the method call order > pretty > easily: > > http://www.artweb-design.de/2008/7/13/expecting-arbitrary-method-calls-in-a-particular-order-in-rspec > > Is there a better way of doing this? > > If not, do you think it would make sense to add this to the RSpec > docs? > http://rspec.info/documentation/mocks/message_expectations.html > > Hey Sven, > > Mock objects have an optional notion of ordering. Check out the > following spec: > > describe "a mock object" do > it "should expect ordered messages" do > foo = mock("ordered mock") > foo.should_receive(:first).ordered > foo.should_receive(:second).ordered > foo.should_receive(:third).ordered > > foo.first > foo.second > foo.third > end > end > > Changing the order in which they''re called will raise an > ExpectationNotMetError. > > Sven, FYI - this is explained on the page you mentioned: > http://rspec.info/documentation/mocks/message_expectations.html > > Hey guys, thanks for the quick answers :) > > Maybe I was not clear enough about what I wanted to spec. Or I > actually do not understand what #ordered does. > > In Pat''s spec above the methods #first, #second and #third are > called on the same object foo and the spec defines the order. That''s > kind of the opposite of my usecase. I wanted to specify that the a > method #run (or whatever) is called on *different* objects in a > particular order. Like: > > filter_1 = mock(''filter_1'') > filter_2 = mock(''filter_2'') > filter_chain << filter_1 > filter_chain << filter_2 > > Now, when the filter_chain is run I want to expect that the filters > are run in the order they were added to the chain: > > filter_chain.run > methods_called_on_individual_filters.should == [''filter_1#run'', > ''filter_2#run''] # pseudo-code > > If that''s possible somehow with should_receive(:run).ordered than at > least it''s not very clear from that docs page which only talks about > expecting the order of methods being called on the same mock, not on > different mocks. ("There are times when you want to specify the > order of messages sent to *a* mock") > > Am I missing something? > > Maybe it''s bit more clear this way: > > class Chain < Array > def run > each{|object| object.run} > end > end > > describe "Expecting the order of methods being called on arbitrary > objects" do > it "works" do > first = mock(''first'') > second = mock(''second'') > > chain = Chain.new > chain << first > chain << second > > second.should_receive(:run).ordered > first.should_receive(:run).ordered > chain.run > end > end > > This passes, of course. > > I''d want to to specify that first#run is run first and second#run is > run second though and I think I can''t do that with > should_receive.ordered > > > > -- > sven fuchs svenfuchs at artweb-design.de > artweb design http://www.artweb-design.de > gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) > d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile) > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > > > > -- > Zach Dennis > http://www.continuousthinking.com > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users-- sven fuchs svenfuchs at artweb-design.de artweb design http://www.artweb-design.de gr?nberger 65 + 49 (0) 30 - 47 98 69 96 (phone) d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)
Ashley Moran
2008-Jul-13 17:17 UTC
[rspec-users] Expecting arbitrary method calls in a particular order
On Jul 13, 2008, at 5:03 pm, Sven Fuchs wrote:> Hey Ashley! > > How''s things? :)Good thanks, just sadly not spent much time using RSpec lately... Spam me off list if you want to catch up!> Wow, yes. > > This also uses the block passed to should_receive, but in a nicer > way than my inital attemp which is a bit chatty. > > It''d look a bit odd when I want to specify the order for a bunch of > methods, but actually I don''t need to do that here. > > Again, this really should be documented. I even started digging into > the RSpec source, but obviously lacked the creativity for this :)I remember posting about this a long time ago. I think it was Aslak that replied. I''d prefer a neater syntax for ordered expectations across mocks. Not too long ago I was working on my database migration tool that has to turn a graph of migrations into a linear sequence before it can apply them, and obviously the order is essential. But the specs look something like... migration_1.should_receive(:apply) do migration_2.should_receive(:apply) do migration_3.should_receive(:apply) do migration_4.should_receive(:apply) do ... which is a bit hideous. I''d prefer something like migration_1.should_receive(:apply) migration_2.should_receive(:apply).after(migration_2.receives(:apply)) ... but I guess that would complicate the implementation. As it''s a relatively uncommon thing I think probably just documenting it is ok for now. Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/