Hello, I recently made a feature request with a patch for terser mocks. http://rubyforge.org/tracker/index.php?func=detail&aid=10412&group_id=1917&atid=7480 Here are some examples with their current equivalents: the_mock.expects.foo(1,2) {|a, b| :bar} the_mock.expects.foo(1,2).returns(:bar) the_mock.expects(:foo).with(1,2) {|a, b| :bar} the_mock.expects(:foo).with(1,2).returns(:bar) The patch is pretty simple too. Also, here is an example from my feature request for mock blocks that does not have a patch yet. http://rubyforge.org/tracker/index.php?func=detail&aid=10413&group_id=1917&atid=7480 the_mock = mock(''The new mock'') do foo(1,2) {:bar} baz(3,4).returns(:foobar) end In the previous block, expectations for foo and baz are being set. This block is equivalent to: the_mock = mock(''The new mock'') the_mock.expects(:foo).with(1,2) {:bar} the_mock.expects(:baz).with(3,4).returns(:foobar) Here is an ActiveRecord type example of the mock block syntax: User.mocks do find(''3'').once {user} destroy(7) end I don''t think this would be too difficult to implement either. WDYT? Thanks, Brian Takita
On 02/05/07, Brian Takita <brian.takita at gmail.com> wrote:> > I recently made a feature request with a patch for terser mocks. > > http://rubyforge.org/tracker/index.php?func=detail&aid=10412&group_id=1917&atid=7480Thanks for the feature request and especially for going to the trouble of writing a patch. I''m sorry for not responding - I''ve been busy with as usual. Here are some examples with their current equivalents:> > the_mock.expects.foo(1,2) {|a, b| :bar} > the_mock.expects.foo(1,2).returns(:bar) > the_mock.expects(:foo).with(1,2) {|a, b| :bar} > the_mock.expects(:foo).with(1,2).returns(:bar)Hmm. I quite like the syntax of the first half, e.g. "the_mock.expects.foo(1,2)", because it''s similar to how the expected method would be called. But I''m not so keen on the block syntax for the return value, e.g. "{|a, b| :bar}", because I don''t think it''s as readable. The patch is pretty simple too. Sorry, I haven''t had a chance to look at the code in the patch yet. Also, here is an example from my feature request for mock blocks that does> not have a patch yet. > > http://rubyforge.org/tracker/index.php?func=detail&aid=10413&group_id=1917&atid=7480 > > the_mock = mock(''The new mock'') do > foo(1,2) {:bar} > baz(3,4).returns(:foobar) > end > > In the previous block, expectations for foo and baz are being set. > This block is equivalent to: > > the_mock = mock(''The new mock'') > the_mock.expects(:foo).with(1,2) {:bar} > the_mock.expects(:baz).with(3,4).returns(:foobar)I''ve been thinking of doing something similar, but I would like to retain the clear distinction between expecting and stubbing... larry = mock() do named(''Larry'') responds_like(Lamb.new) expects(:baa) stubs(:meh) end Here is an ActiveRecord type example of the mock block syntax:> User.mocks do > find(''3'').once {user} > destroy(7) > end > > I don''t think this would be too difficult to implement either. > > WDYT? >Thanks for your suggestions. What does anybody else think? -- James. http://blog.floehopper.org
+1 to both parts of the original post. I implemented this in my own mocking framework (everyone should write a mocking framework - it''s fun!) using a similar syntax, like this: mock_sheep = mock(Sheep) # see earlier thread mock_sheep.expects do |m| m.chew_grass # method call m.say("baa") # method with params m.jump(kind_of(Hedge)) # matchers in mocks m.ask_time.returns("3 o''clock") # return values m.shoot.raises(DeceasedSheepError, "ouch") # exceptions end It''s easier on the eye than :labels_for_methods. Likewise, you can stub the same way, just with stub{|m| ...} instead of expect{|m| ...}: mock_sheep.stubs { |m| m.dont_care_about_this m.this_might_get_called.returns("Tuesday") } It''s easy to implement by temporarily replacing method_missing in the mock and then passing it into the block. I found it led to nicely readable mock interactions, and it''s a useful alternative syntax. Cheers, Dan ps. You''re welcome to the original code if you think it might help. It''s not very clever though ;) James Mead wrote:> On 02/05/07, Brian Takita <brian.takita at gmail.com> wrote: > >> I recently made a feature request with a patch for terser mocks. >> >> http://rubyforge.org/tracker/index.php?func=detail&aid=10412&group_id=1917&atid=7480 >> > > > Thanks for the feature request and especially for going to the trouble of > writing a patch. > I''m sorry for not responding - I''ve been busy with as usual. > > Here are some examples with their current equivalents: > >> the_mock.expects.foo(1,2) {|a, b| :bar} >> the_mock.expects.foo(1,2).returns(:bar) >> the_mock.expects(:foo).with(1,2) {|a, b| :bar} >> the_mock.expects(:foo).with(1,2).returns(:bar) >> > > > Hmm. I quite like the syntax of the first half, e.g. > "the_mock.expects.foo(1,2)", because it''s similar to how the expected method > would be called. But I''m not so keen on the block syntax for the return > value, e.g. "{|a, b| :bar}", because I don''t think it''s as readable. > > The patch is pretty simple too. > > > Sorry, I haven''t had a chance to look at the code in the patch yet. > > Also, here is an example from my feature request for mock blocks that does > >> not have a patch yet. >> >> http://rubyforge.org/tracker/index.php?func=detail&aid=10413&group_id=1917&atid=7480 >> >> the_mock = mock(''The new mock'') do >> foo(1,2) {:bar} >> baz(3,4).returns(:foobar) >> end >> >> In the previous block, expectations for foo and baz are being set. >> This block is equivalent to: >> >> the_mock = mock(''The new mock'') >> the_mock.expects(:foo).with(1,2) {:bar} >> the_mock.expects(:baz).with(3,4).returns(:foobar) >> > > > I''ve been thinking of doing something similar, but I would like to retain > the clear distinction between expecting and stubbing... > > larry = mock() do > named(''Larry'') > responds_like(Lamb.new) > expects(:baa) > stubs(:meh) > end > > Here is an ActiveRecord type example of the mock block syntax: > >> User.mocks do >> find(''3'').once {user} >> destroy(7) >> end >> >> I don''t think this would be too difficult to implement either. >> >> WDYT? >> >> > > Thanks for your suggestions. What does anybody else think? > >
On 5/2/07, James Mead <jamesmead44 at gmail.com> wrote:> > On 02/05/07, Brian Takita <brian.takita at gmail.com> wrote: > > > > I recently made a feature request with a patch for terser mocks. > > > > > http://rubyforge.org/tracker/index.php?func=detail&aid=10412&group_id=1917&atid=7480 > > > Thanks for the feature request and especially for going to the trouble of > writing a patch. > I''m sorry for not responding - I''ve been busy with as usual. > > Here are some examples with their current equivalents: > > > > the_mock.expects.foo(1,2) {|a, b| :bar} > > the_mock.expects.foo(1,2).returns(:bar) > > the_mock.expects(:foo).with(1,2) {|a, b| :bar} > > the_mock.expects(:foo).with(1,2).returns(:bar) > > > Hmm. I quite like the syntax of the first half, e.g. > "the_mock.expects.foo(1,2)", because it''s similar to how the expected > method > would be called. But I''m not so keen on the block syntax for the return > value, e.g. "{|a, b| :bar}", because I don''t think it''s as readable.The block I provided actually does more than it needs to. This is what it should have been: the_mock.expects.foo(1,2) {:bar} Is the unreadability from the fact that ''returns'' is not explicitly stated or from the fact that there was unneeded code ''|a, b|''? The patch is pretty simple too.> > > Sorry, I haven''t had a chance to look at the code in the patch yet. > > Also, here is an example from my feature request for mock blocks that does > > not have a patch yet. > > > > > http://rubyforge.org/tracker/index.php?func=detail&aid=10413&group_id=1917&atid=7480 > > > > the_mock = mock(''The new mock'') do > > foo(1,2) {:bar} > > baz(3,4).returns(:foobar) > > end > > > > In the previous block, expectations for foo and baz are being set. > > This block is equivalent to: > > > > the_mock = mock(''The new mock'') > > the_mock.expects(:foo).with(1,2) {:bar} > > the_mock.expects(:baz).with(3,4).returns(:foobar) > > > I''ve been thinking of doing something similar, but I would like to retain > the clear distinction between expecting and stubbing... > > larry = mock() do > named(''Larry'') > responds_like(Lamb.new) > expects(:baa) > stubs(:meh) > end>From Dan:> It''s easier on the eye than :labels_for_methodsI think it''s easier on the eye because it simulates how the method is actually used. I found it led to nicely readable mock interactions, and it''s a useful> alternative syntax. >I like that that you found it useful in practice :) A common complaint I''ve heard about mocks is that they are less readable than using plain domain objects. mock_sheep.expects do |m|> m.chew_grass # method call > m.say("baa") # method with params > m.jump(kind_of(Hedge)) # matchers in mocks > m.ask_time.returns("3 o''clock") # return values > m.shoot.raises (DeceasedSheepError, "ouch") # exceptions > end > It''s easy to implement by temporarily replacing method_missing in the > mock and then passing it into the block. >You can also have a "Recorder" type object that implements method_missing and instance eval the block. That way, you can avoid having to pass in the reference to the mock ''|m|''. Here is an ActiveRecord type example of the mock block syntax:> > User.mocks do > > find(''3'').once {user} > > destroy(7) > > end > > > > I don''t think this would be too difficult to implement either. > > > > WDYT? > > > > Thanks for your suggestions. What does anybody else think? > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >
Brian Takita wrote:>> You can also have a "Recorder" type object that implements method_missing >> and instance eval the block. That way, you can avoid having to pass in the >> reference to the mock ''|m|''. >>Yes, you can have the object just yield to the block, but it looks less intuitive to me, because I have to think about what the value of "self" is for find(''3'') or destroy(7). The parameter makes it explicit that it''s on the mock. That''s the only reason I went with one rather than the other. Cheers, Dan