From jamesmead44 at gmail.com Sun Apr 1 17:25:51 2007 From: jamesmead44 at gmail.com (James Mead) Date: Sun, 1 Apr 2007 22:25:51 +0100 Subject: [mocha-developer] problem with using any_instance In-Reply-To: References: <1db558f00703301050w48478a08lffb2f95795d8826b@mail.gmail.com> Message-ID: <1db558f00704011425v36969f9u90c6a59a464d40f9@mail.gmail.com> It looks like the critical aspect of your failing test is the fact that you are stubbing a private method. Originally Mocha did not allow stubbing of private methods. Somehow accidentally it became allowed. Stubbing private methods isn't a good idea, because it couples the test to the internals of the class. There seems to be a bug with stubbing a private method. I'll look into it, but in the meantime you can fix your test if you are able to make the stubbed method public. Thanks. -- James. http://blog.floehopper.org From hayafirst at gmail.com Mon Apr 2 08:42:28 2007 From: hayafirst at gmail.com (Yi Wen) Date: Mon, 2 Apr 2007 07:42:28 -0500 Subject: [mocha-developer] problem with using any_instance In-Reply-To: <1db558f00704011425v36969f9u90c6a59a464d40f9@mail.gmail.com> References: <1db558f00703301050w48478a08lffb2f95795d8826b@mail.gmail.com> <1db558f00704011425v36969f9u90c6a59a464d40f9@mail.gmail.com> Message-ID: Thanks James, I also looked into the Mocha code. It seems in AnyInstance class, restore_original_method uses "method_defined?" and this method matches only public and protected methods in the module/included classes, etc. (And method_defined? is used in many other cases as well). I think that's why the original private method_name was not restored. stubbee.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.method_defined?(hidden_method) I agree with you that stubbing a private method is not a good idea in general. So I agree with you that what need to be done is to disallow mocking private methods explicitly. From what I can see in a very quick glance, "stubs" method is not guarded with any checking... Anyway, just trying to be helpful. And thanks again, your correspondence helped a lot. Yi On 4/1/07, James Mead wrote: > > It looks like the critical aspect of your failing test is the fact that > you > are stubbing a private method. > > Originally Mocha did not allow stubbing of private methods. Somehow > accidentally it became allowed. Stubbing private methods isn't a good > idea, > because it couples the test to the internals of the class. > > There seems to be a bug with stubbing a private method. I'll look into it, > but in the meantime you can fix your test if you are able to make the > stubbed method public. > > Thanks. > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From jamesthepiper at gmail.com Mon Apr 2 12:24:02 2007 From: jamesthepiper at gmail.com (James Moore) Date: Mon, 2 Apr 2007 09:24:02 -0700 Subject: [mocha-developer] Automatically mocking ActiveRecord methods In-Reply-To: <1db558f00703270701l3f35d334ved9e3f62fb13fce0@mail.gmail.com> References: <7cfed280703181003q2ac0a225v676f0aae214f3ad0@mail.gmail.com> <1db558f00703270701l3f35d334ved9e3f62fb13fce0@mail.gmail.com> Message-ID: <7cfed280704020924o347d9824g461c935abf6f4053@mail.gmail.com> After I wrote this, I started to have second thoughts. It seemed like this was mostly useful in Rails controller tests as a way of abstracting away the database. But then I started running into too many situations where I had handcrafted SQL in use, and mocking that clearly was the wrong way to go. (We're storing something that looks like a directory tree in SQL records, and the live installation has a few million entries. The standard rails things like acts_as_tree are hopeless for performance without handcrafting some queries.) I'm now wondering whether a better way to do this is to add a facility to add callbacks that can create mocks and stubs when a particular object is instantiated from the database. A sort of cleanup method on Rails find*() methods that will allow you to do mock/stub methods on an object with a particular id (or some set of criteria) when it's created. In any case, I agree that it should be some sort of addon facility, and I don't think there's any reason why it would need to touch Object directly. - James Moore On 3/27/07, James Mead wrote: > > I can see why you might want to do this. I'm not sure I would want to add > another public instance method to Object - recently I've been looking into > how to reduce the number of such methods added to Object. Also I don't > really want to incorporate any more Rails-specific code into Mocha. The > Mocha Rails plugin is currently little more than a conditional require > statement. > > Can I suggest you consider creating your own Rails plugin and see how > things > go...? > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From fred at 82ask.com Mon Apr 2 12:29:14 2007 From: fred at 82ask.com (Frederick Cheung) Date: Mon, 2 Apr 2007 17:29:14 +0100 Subject: [mocha-developer] Automatically mocking ActiveRecord methods In-Reply-To: <7cfed280704020924o347d9824g461c935abf6f4053@mail.gmail.com> References: <7cfed280703181003q2ac0a225v676f0aae214f3ad0@mail.gmail.com> <1db558f00703270701l3f35d334ved9e3f62fb13fce0@mail.gmail.com> <7cfed280704020924o347d9824g461c935abf6f4053@mail.gmail.com> Message-ID: On 2 Apr 2007, at 17:24, James Moore wrote: > > I'm now wondering whether a better way to do this is to add a > facility to > add callbacks that can create mocks and stubs when a particular > object is > instantiated from the database. A sort of cleanup method on Rails > find*() > methods that will allow you to do mock/stub methods on an object > with a > particular id (or some set of criteria) when it's created. I did this via the after_find callback a few weeks ago. I posted my code here when I did it maybe you'll find some inspiration there ? Fred > > In any case, I agree that it should be some sort of addon facility, > and I > don't think there's any reason why it would need to touch Object > directly. > > - James Moore > > On 3/27/07, James Mead wrote: >> >> I can see why you might want to do this. I'm not sure I would want >> to add >> another public instance method to Object - recently I've been >> looking into >> how to reduce the number of such methods added to Object. Also I >> don't >> really want to incorporate any more Rails-specific code into >> Mocha. The >> Mocha Rails plugin is currently little more than a conditional >> require >> statement. >> >> Can I suggest you consider creating your own Rails plugin and see how >> things >> go...? >> >> -- >> James. >> http://blog.floehopper.org >> _______________________________________________ >> mocha-developer mailing list >> mocha-developer at rubyforge.org >> http://rubyforge.org/mailman/listinfo/mocha-developer >> > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From jamesmead44 at gmail.com Tue Apr 3 04:55:21 2007 From: jamesmead44 at gmail.com (James Mead) Date: Tue, 3 Apr 2007 09:55:21 +0100 Subject: [mocha-developer] problem with using any_instance In-Reply-To: References: <1db558f00703301050w48478a08lffb2f95795d8826b@mail.gmail.com> <1db558f00704011425v36969f9u90c6a59a464d40f9@mail.gmail.com> Message-ID: <1db558f00704030155m5e88a3cfi32f20171d0592e50@mail.gmail.com> Thanks for looking into it and identifying the problem - I haven't had much time recently. It sounds as if the problem is as I suspected. Thanks for your help. -- James. http://blog.floehopper.org From rsanheim at gmail.com Tue Apr 3 12:39:33 2007 From: rsanheim at gmail.com (Rob Sanheim) Date: Tue, 3 Apr 2007 11:39:33 -0500 Subject: [mocha-developer] small suggestion - once method on Expectation Message-ID: I find that a lot of times I want to ensure a method gets called exactly once, for example when testing caching or eager loading. What does the list think of adding this little humane method to Mocha::Expectation? def once times(1) self end which means this: def test_should_only_grab_post_once_from_the_cache Post.expects(:get_cache).with(google_vs_yahoo.id).times(1) comments.first.post comments.first.post end becomes: def test_should_only_grab_post_once_from_the_cache Post.expects(:get_cache).with(google_vs_yahoo.id).once comments.first.post comments.first.post end Not a huge difference, but a little nicer and ruby-ish in the same way we have Array.first, Array.last, etc. - Rob From dchelimsky at gmail.com Tue Apr 3 13:49:19 2007 From: dchelimsky at gmail.com (David Chelimsky) Date: Tue, 3 Apr 2007 12:49:19 -0500 Subject: [mocha-developer] small suggestion - once method on Expectation In-Reply-To: References: Message-ID: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> On 4/3/07, Rob Sanheim wrote: > I find that a lot of times I want to ensure a method gets called > exactly once, for example when testing caching or eager loading. What > does the list think of adding this little humane method to > Mocha::Expectation? > > def once > times(1) > self > end > > which means this: > def test_should_only_grab_post_once_from_the_cache > Post.expects(:get_cache).with(google_vs_yahoo.id).times(1) > comments.first.post > comments.first.post > end > > becomes: > def test_should_only_grab_post_once_from_the_cache > Post.expects(:get_cache).with(google_vs_yahoo.id).once > comments.first.post > comments.first.post > end > > Not a huge difference, but a little nicer and ruby-ish in the same way > we have Array.first, Array.last, etc. Your suggestion might make things more clear, but once is implied w/ expects (and no times): def test_should_only_grab_post_once_from_the_cache Post.expects(:get_cache).with(google_vs_yahoo.id) comments.first.post comments.first.post end This would fail as you expect. > > - Rob > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From jamesmead44 at gmail.com Tue Apr 3 14:19:31 2007 From: jamesmead44 at gmail.com (James Mead) Date: Tue, 3 Apr 2007 19:19:31 +0100 Subject: [mocha-developer] small suggestion - once method on Expectation In-Reply-To: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> References: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> Message-ID: <1db558f00704031119i1a71dca1s95b0bee3996e7c67@mail.gmail.com> David is right. I have occasionally thought about adding an "exactly_once" method for readability/emphasis. Is this what you have in mind? Or was it not clear from the documentation that the default was to expect a call exactly once? It would be good to have your feedback. -- James. http://blog.floehopper.org From kevin.clark at gmail.com Tue Apr 3 14:33:13 2007 From: kevin.clark at gmail.com (Kevin Clark) Date: Tue, 3 Apr 2007 11:33:13 -0700 Subject: [mocha-developer] small suggestion - once method on Expectation In-Reply-To: <1db558f00704031119i1a71dca1s95b0bee3996e7c67@mail.gmail.com> References: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> <1db558f00704031119i1a71dca1s95b0bee3996e7c67@mail.gmail.com> Message-ID: I find myself using .once here and there by accident. It'd be nice to have :) exactly_once work work too On 4/3/07, James Mead wrote: > David is right. > > I have occasionally thought about adding an "exactly_once" method for > readability/emphasis. > > Is this what you have in mind? Or was it not clear from the documentation > that the default was to expect a call exactly once? > > It would be good to have your feedback. > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > -- Kevin Clark http://glu.ttono.us From rsanheim at gmail.com Tue Apr 3 14:40:22 2007 From: rsanheim at gmail.com (Rob Sanheim) Date: Tue, 3 Apr 2007 13:40:22 -0500 Subject: [mocha-developer] small suggestion - once method on Expectation In-Reply-To: References: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> <1db558f00704031119i1a71dca1s95b0bee3996e7c67@mail.gmail.com> Message-ID: On 4/3/07, Kevin Clark wrote: > I find myself using .once here and there by accident. It'd be nice to have :) > exactly_once work work too > Yeah, I didn't realize .once was implicit, and I've often tried to use .once since it seems like it would be consistent with never/times/etc. I think having the explicit call available for readability would be great in addition to having a note about the implicit nature of it in the examples somewhere. The examples are very useful btw - I always refer to them from w/i textmate when I forget how to call something. Documentation right there w/i the code is much better then having to drop out to google to look things up. thanks, Rob From jamesmead44 at gmail.com Tue Apr 3 15:26:12 2007 From: jamesmead44 at gmail.com (James Mead) Date: Tue, 3 Apr 2007 20:26:12 +0100 Subject: [mocha-developer] small suggestion - once method on Expectation In-Reply-To: References: <57c63afe0704031049m41ba5dfand60806f35a4db58b@mail.gmail.com> <1db558f00704031119i1a71dca1s95b0bee3996e7c67@mail.gmail.com> Message-ID: <1db558f00704031226t2c2516b5ia21baa0279ceb9df@mail.gmail.com> I've just added Expectation#once for your delectation (revision 110), which hopefully makes the API less surprising :-) -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 11 10:36:16 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 11 Apr 2007 15:36:16 +0100 Subject: [mocha-developer] Fwd: [ mocha-Bugs-6416 ] Mock objects shouldn't define #to_s In-Reply-To: <20070411140737.B07A65240ABC@rubyforge.org> References: <20070411140737.B07A65240ABC@rubyforge.org> Message-ID: <1db558f00704110736i5a65b449wc2660c4f1e20fbc7@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 11-Apr-2007 15:07 Subject: [ mocha-Bugs-6416 ] Mock objects shouldn't define #to_s To: noreply at rubyforge.org Bugs item #6416, was opened at 2006-10-31 15:34 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=6416&group_id=1917 Category: None Group: None Status: Open Resolution: None Priority: 3 Submitted By: James Adam (lazyatom) Assigned to: Nobody (None) Summary: Mock objects shouldn't define #to_s Initial Comment: Creating a mock object which expects the #to_s method is impossible at present, and results in an unattainable expectation: mock(:whatever, :to_s => 'hi') puts mock.to_s # ==> # It's almost certainly desirable to be able to mock the #to_s method, so the inheritted #to_s in Mocha::Mock should either be removed, or some explicit behaviour added which can handle setting expectations for methods already present on that object. ---------------------------------------------------------------------- >Comment By: James Mead (jamesmead) Date: 2007-04-11 14:07 Message: Sorry for the delayed response. I think this was fixed in revision 86 which should have made it into release 0.4. Can you let me know if this is still broken? Thanks. ---------------------------------------------------------------------- Comment By: James Mead (jamesmead) Date: 2006-11-01 11:06 Message: This is a known issue. I hope to commit a fix soon. ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=6416&group_id=1917 -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 11 10:36:44 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 11 Apr 2007 15:36:44 +0100 Subject: [mocha-developer] Fwd: [ mocha-Bugs-5892 ] Using a setup method in test_case_class destroys subsequent test cases In-Reply-To: <20070411142421.D05C55240AF5@rubyforge.org> References: <20070411142421.D05C55240AF5@rubyforge.org> Message-ID: <1db558f00704110736w7c755697xe56bd57423ea3445@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 11-Apr-2007 15:24 Subject: [ mocha-Bugs-5892 ] Using a setup method in test_case_class destroys subsequent test cases To: noreply at rubyforge.org Bugs item #5892, was opened at 2006-09-25 07:49 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=5892&group_id=1917 Category: None Group: None Status: Open Resolution: None Priority: 3 Submitted By: Craig Ambrose (craigambrose) Assigned to: Nobody (None) Summary: Using a setup method in test_case_class destroys subsequent test cases Initial Comment: Using a method called setup within a Test::Unit::TestCase derived class works as expected once you start using mocha and stubba, providing that you run only that test file. If you run several such files, subsequent ones throw exceptions because the Stubba method setup_stubs is no longer getting called (your test case setup method has overwritten it) and thus $stubba is nil. The error you actually see, if you are usings @your_objects.stubs().... is something like: NoMethodError: You have a nil object when you didn't expect it! The error occurred while evaluating nil.stub ---------------------------------------------------------------------- >Comment By: James Mead (jamesmead) Date: 2007-04-11 14:24 Message: I've just tried to reproduce this bug with both recent and old versions of Mocha, but without success. Can you let me know if you are still seeing the bug? Thanks. ---------------------------------------------------------------------- Comment By: James Mead (jamesmead) Date: 2006-11-01 11:32 Message: Sorry for the late response - I didn't get any notification. You'd get a faster response on the developer mailing list ( http://rubyforge.org/mailman/listinfo/mocha-developer). With what version of Mocha do you see this issue? The setup/teardown mechanism has changed significantly in HEAD and I hope to do a new release soon. I suspect you won't see the problem with the latest version. Let me know either way. ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=5892&group_id=1917 -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 11 10:37:02 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 11 Apr 2007 15:37:02 +0100 Subject: [mocha-developer] Fwd: [ mocha-Feature Requests-5856 ] Stubbing of private methods should be allowed In-Reply-To: <20070411143131.69DBE5240B0F@rubyforge.org> References: <20070411143131.69DBE5240B0F@rubyforge.org> Message-ID: <1db558f00704110737y7b0e4b95uec1dd0b8f6e6b092@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 11-Apr-2007 15:31 Subject: [ mocha-Feature Requests-5856 ] Stubbing of private methods should be allowed To: noreply at rubyforge.org Feature Requests item #5856, was opened at 2006-09-22 17:03 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7480&aid=5856&group_id=1917 Category: None Group: None Status: Open Priority: 3 Submitted By: Christian Romney (xmlblog) Assigned to: Nobody (None) Summary: Stubbing of private methods should be allowed Initial Comment: I have a private method in my Rails controller that does some processing. Based on the return value of this method, a particular action decides what to do. I do not want to make this method public, because public methods in a controller are callable from a URL. Below is a patch to enable stubbing of private methods. Index: lib/stubba/instance_method.rb =================================================================== --- lib/stubba/instance_method.rb (revision 57) +++ lib/stubba/instance_method.rb (working copy) @@ -13,8 +13,9 @@ # intentionally empty end - def exists? - stubbee.respond_to?(method) + def exists? + #stubbee.respond_to?(method) + (stubbee.methods | stubbee.private_methods).include?(method.to_s) end end ---------------------------------------------------------------------- >Comment By: James Mead (jamesmead) Date: 2007-04-11 14:31 Message: I don't know whether you have noticed, but this has accidentally become possible in more recent versions of Mocha! However, I intend to reintroduce the restriction soon. Stubbing private methods is not in general a good idea, because it couples your test to the internal implementation of the class under test. Have you considered moving the method into another class e.g. an appropriate model class. See Jamis Buck's blog posts like this one - http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model. ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7480&aid=5856&group_id=1917 -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 11 10:37:21 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 11 Apr 2007 15:37:21 +0100 Subject: [mocha-developer] Fwd: [ mocha-Bugs-8687 ] Block's return value is dropped on stubbed yielding methods. In-Reply-To: <20070411143147.725EA5240B0F@rubyforge.org> References: <20070411143147.725EA5240B0F@rubyforge.org> Message-ID: <1db558f00704110737r5f3dd38drdc7610283abadc62@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 11-Apr-2007 15:31 Subject: [ mocha-Bugs-8687 ] Block's return value is dropped on stubbed yielding methods. To: noreply at rubyforge.org Bugs item #8687, was opened at 2007-02-15 17:29 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=8687&group_id=1917 Category: None Group: None Status: Open Resolution: None Priority: 3 Submitted By: Erik Hetzner (egh) Assigned to: Nobody (None) Summary: Block's return value is dropped on stubbed yielding methods. Initial Comment: Best explained with an example: test: foo = mock() bar = mock().stubs(:get_baz).returns(:baz) foo.stubs(:with_something).yields(bar) real code: baz = foo.with_something do |bar| bar.get_baz.to_s end baz should now be "baz", but is nil because we have not specified a return value for the stub. Now, we could set add .returns("baz"), but that means that the block isn't really tested. I have attached a file patches on a yields_and_returns method to Mocha::Expecatation & Mocha::Stub which will return the block's return value. foo = Mocha::Mock.new bar = Mocha::Mock.new bar.stubs(:get_baz).returns(:baz) foo.stubs(:with_something).yields_and_returns(bar) baz = foo.with_something do |bar| bar.get_baz.to_s end ---------------------------------------------------------------------- >Comment By: Erik Hetzner (egh) Date: 2007-04-11 07:31 Message: Hi James, Sorry I wasn't more clear. I could certainly change my code, but I have existing code that I want to test, & I don't want to have to change my code so that I can test it. My code uses this with_something idiom & returns the value which the yielded block returns. I can't test this with Mocha's yields builder because it does not return the value with is returned by the yield block. The code: baz = foo.with_something do |bar| bar.get_baz.to_s end is real code which I want to test with a mocked foo & bar objects. ---------------------------------------------------------------------- Comment By: James Mead (jamesmead) Date: 2007-04-11 07:03 Message: Hi Erik, Thanks for the bug report & suggested patch. To be honest I can't see anything wrong with Mocha's behaviour in the example you've given. It's not obvious what you are trying to test. Can you not do something like this... def test_me foo = mock() bar = mock() bar.stubs(:get_baz).returns(:baz) foo.stubs(:with_something).yields(bar) baz = nil foo.with_something do |bar| baz = bar.get_baz.to_s end assert_equal 'baz', baz end (see http://pastie.caboo.se/53041 for syntax highlighted version) ...so I don't really see the need for the yields_and_returns method you are suggesting. Does that make sense? If not, can you try to explain more fully what exactly it is that you are trying to test, ideally with full code examples. Thanks, James. ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=8687&group_id=1917 -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 11 10:42:29 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 11 Apr 2007 15:42:29 +0100 Subject: [mocha-developer] Fwd: [ mocha-Feature Requests-7119 ] ability to specify call order In-Reply-To: <20070411143958.DC92B5240B2E@rubyforge.org> References: <20070411143958.DC92B5240B2E@rubyforge.org> Message-ID: <1db558f00704110742r67079885x64de5dbb3cb33f73@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 11-Apr-2007 15:39 Subject: [ mocha-Feature Requests-7119 ] ability to specify call order To: noreply at rubyforge.org Feature Requests item #7119, was opened at 2006-12-06 00:30 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7480&aid=7119&group_id=1917 Category: None Group: None Status: Open Priority: 3 Submitted By: Jerrett Taylor (ennoia) Assigned to: Nobody (None) Summary: ability to specify call order Initial Comment: something like flexmock's "ordered(n)" would be handy! ---------------------------------------------------------------------- >Comment By: James Mead (jamesmead) Date: 2007-04-11 14:39 Message: Specifying the expected order of invocations been on the todo list for quite a while - hopefully we'll get round to it soon! ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7480&aid=7119&group_id=1917 -- James. http://blog.floehopper.org From ned.wolpert at gmail.com Wed Apr 11 16:56:14 2007 From: ned.wolpert at gmail.com (Ned Wolpert) Date: Wed, 11 Apr 2007 13:56:14 -0700 Subject: [mocha-developer] Feature request... I think... Message-ID: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> Folks- I just started using Mocha and I wanted to try something but I couldn't get it to work. I'm coming from the Java world, so my approach may not be optimal for Ruby. Say I'm testing a.do_something() which calls b.do_other_thing() twice, but I really don't want to change b.do_other_thing(), just 'expect' it to be called twice. I know I can b.expect(:do_other_thing).times(2) but it changes the whole method. Unless I'm doing something wrong, I can't do this in mocha. I know its not mocking the object or method. But what I really want to do is put in a hook into validate the state of the object at the point of time into and out of the method. If this isn't the place of mocha, where should I do it? (And yes, one can easily argue that I'm likely making my test case too complicated if I have to do this, but we found an esoteric bug on a short-lived object and having a test to check for this specific case would help make sure that bug stays away.) -- Virtually, Ned Wolpert "Settle thy studies, Faustus, and begin..." --Marlowe Discere docendo... From jamesmead44 at gmail.com Thu Apr 12 04:25:04 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 12 Apr 2007 09:25:04 +0100 Subject: [mocha-developer] Fwd: [ mocha-Bugs-5892 ] Using a setup method in test_case_class destroys subsequent test cases In-Reply-To: <20070412082358.421AC5240AD5@rubyforge.org> References: <20070412082358.421AC5240AD5@rubyforge.org> Message-ID: <1db558f00704120125wfa3d79ayb2c4956485ac47ab@mail.gmail.com> ---------- Forwarded message ---------- From: noreply at rubyforge.org Date: 12-Apr-2007 09:23 Subject: [ mocha-Bugs-5892 ] Using a setup method in test_case_class destroys subsequent test cases To: noreply at rubyforge.org Bugs item #5892, was opened at 2006-09-25 07:49 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=5892&group_id=1917 Category: None Group: None >Status: Closed Resolution: None Priority: 3 Submitted By: Craig Ambrose (craigambrose) Assigned to: Nobody (None) Summary: Using a setup method in test_case_class destroys subsequent test cases Initial Comment: Using a method called setup within a Test::Unit::TestCase derived class works as expected once you start using mocha and stubba, providing that you run only that test file. If you run several such files, subsequent ones throw exceptions because the Stubba method setup_stubs is no longer getting called (your test case setup method has overwritten it) and thus $stubba is nil. The error you actually see, if you are usings @your_objects.stubs().... is something like: NoMethodError: You have a nil object when you didn't expect it! The error occurred while evaluating nil.stub ---------------------------------------------------------------------- >Comment By: James Mead (jamesmead) Date: 2007-04-12 08:23 Message: Thanks. I'm sure you did see it. Sorry I've taken so long to respond. ---------------------------------------------------------------------- Comment By: Craig Ambrose (craigambrose) Date: 2007-04-12 01:38 Message: Hi James, I can't reproduct this anymore either. I recall being pretty confident that it was a bug back when I filed it, but that was a long time ago, and I presume that it's been fixed in a subsequent release. I've been using mocha quite a bit recently without any such problems. ---------------------------------------------------------------------- Comment By: James Mead (jamesmead) Date: 2007-04-11 14:24 Message: I've just tried to reproduce this bug with both recent and old versions of Mocha, but without success. Can you let me know if you are still seeing the bug? Thanks. ---------------------------------------------------------------------- Comment By: James Mead (jamesmead) Date: 2006-11-01 11:32 Message: Sorry for the late response - I didn't get any notification. You'd get a faster response on the developer mailing list ( http://rubyforge.org/mailman/listinfo/mocha-developer). With what version of Mocha do you see this issue? The setup/teardown mechanism has changed significantly in HEAD and I hope to do a new release soon. I suspect you won't see the problem with the latest version. Let me know either way. ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=7477&aid=5892&group_id=1917 -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Thu Apr 12 13:21:46 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 12 Apr 2007 18:21:46 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes Message-ID: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> I've finally managed to find some time to do some serious work on Mocha. There are some code snippets on my blog (http://blog.floehopper.org/articles/2007/04/12/preview-of-latest-mocha-changes) showing the new functionality available in trunk (revision 128). I don't don't know how many people out there are using trunk, but it would be great to get some feedback on these changes before I make a new release. In particular I'd like to know whether? - I've broken anybody's tests. - Anybody has a legitimate use for parameter_block in Expectation#with that they don't think will be handled by a suitable parameter matcher i.e. using the current behaviour where the block is passed the parameters and the result of the block determines whether the expectation matches. I'm planning on deprecating this soon. - Anybody has a legitimate use for passing in an instance of Proc to Expectation#returns i.e. using the current behaviour where the Proc gets executed to generate a return value. I'm planning on deprecating this soon as well. Thanks for all your ideas and suggestions. -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Thu Apr 12 13:54:37 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 12 Apr 2007 18:54:37 +0100 Subject: [mocha-developer] Feature request... I think... In-Reply-To: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> References: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> Message-ID: <1db558f00704121054r593f7dcck1c7687a94b578915@mail.gmail.com> Sorry, Mocha is unlikely to support anything like this. It's too far away from the idea of mock objects. Can you not refactor the code so that you can write sensible unit tests around the defect? -- James. http://blog.floehopper.org From fred at 82ask.com Thu Apr 12 14:10:05 2007 From: fred at 82ask.com (Frederick Cheung) Date: Thu, 12 Apr 2007 19:10:05 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> Message-ID: <4436825E-980C-4E19-A899-11F5CA5506EA@82ask.com> On 12 Apr 2007, at 18:21, James Mead wrote: > - Anybody has a legitimate use for passing in an instance of Proc to > Expectation#returns i.e. using the current behaviour where the Proc > gets executed to generate a return value. I'm planning on deprecating > this soon as well. I use this. Some of my tests test that my models behave correctly in the presence of certain exception being thrown (eg a socket connection dieing, ActiveRecord raising a StaleObjectError etc...) I use the Proc behaviour so that the first call raises and the second call doesn't i.e actions = [lambda {raise Foo}, lambda {:blah}] thing.stubs(:foo).returns(lambda {actions.shift.call}) Fred From jamesmead44 at gmail.com Thu Apr 12 15:56:17 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 12 Apr 2007 20:56:17 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <4436825E-980C-4E19-A899-11F5CA5506EA@82ask.com> References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> <4436825E-980C-4E19-A899-11F5CA5506EA@82ask.com> Message-ID: <1db558f00704121256t6024ad97tee39304854b6ea16@mail.gmail.com> The idea would be you could use the new functionality to do something like this instead... thing.stubs(:foo).raises(Foo).then.returns(:blah) Does that make sense? -- James. http://blog.floehopper.org From fred at 82ask.com Thu Apr 12 17:17:38 2007 From: fred at 82ask.com (Frederick Cheung) Date: Thu, 12 Apr 2007 22:17:38 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <1db558f00704121256t6024ad97tee39304854b6ea16@mail.gmail.com> References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> <4436825E-980C-4E19-A899-11F5CA5506EA@82ask.com> <1db558f00704121256t6024ad97tee39304854b6ea16@mail.gmail.com> Message-ID: D'oh, hadn't read past the list of things that were being deprecated. All looks good to me ! Fred On 12 Apr 2007, at 20:56, James Mead wrote: > The idea would be you could use the new functionality to do something > like this instead... > > thing.stubs(:foo).raises(Foo).then.returns(:blah) > > Does that make sense? > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From ned.wolpert at gmail.com Thu Apr 12 17:46:40 2007 From: ned.wolpert at gmail.com (Ned Wolpert) Date: Thu, 12 Apr 2007 14:46:40 -0700 Subject: [mocha-developer] Feature request... I think... In-Reply-To: <1db558f00704121054r593f7dcck1c7687a94b578915@mail.gmail.com> References: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> <1db558f00704121054r593f7dcck1c7687a94b578915@mail.gmail.com> Message-ID: <33cb339b0704121446o5d7cf3e1u5119486ac8089d17@mail.gmail.com> One would think I could refactor the code, so yes. The optimal way to deal with this is to write the test case that shows the bug, then fix the bug, rather then refactor first. I was hoping that I could use Mocha to help do just that. So it goes... BTW, I enjoy using Mocha more then EasyMock... its a great project. On 4/12/07, James Mead wrote: > Sorry, Mocha is unlikely to support anything like this. It's too far away > from the idea of mock objects. > > Can you not refactor the code so that you can write sensible unit tests > around the defect? > -- Virtually, Ned Wolpert "Settle thy studies, Faustus, and begin..." --Marlowe Discere docendo... From kevin.clark at gmail.com Thu Apr 12 18:52:41 2007 From: kevin.clark at gmail.com (Kevin Clark) Date: Thu, 12 Apr 2007 15:52:41 -0700 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> Message-ID: This looks awesome James. I now wish I'd submitted a Railsconf talk about mocha instead of heckle (no love for the heckle these days :( ). It just gets better and better. On 4/12/07, James Mead wrote: > I've finally managed to find some time to do some serious work on > Mocha. There are some code snippets on my blog > (http://blog.floehopper.org/articles/2007/04/12/preview-of-latest-mocha-changes) > showing the new functionality available in trunk (revision 128). I > don't don't know how many people out there are using trunk, but it > would be great to get some feedback on these changes before I make a > new release. In particular I'd like to know whether? > > - I've broken anybody's tests. > - Anybody has a legitimate use for parameter_block in Expectation#with > that they don't think will be handled by a suitable parameter matcher > i.e. using the current behaviour where the block is passed the > parameters and the result of the block determines whether the > expectation matches. I'm planning on deprecating this soon. > - Anybody has a legitimate use for passing in an instance of Proc to > Expectation#returns i.e. using the current behaviour where the Proc > gets executed to generate a return value. I'm planning on deprecating > this soon as well. > > Thanks for all your ideas and suggestions. > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > -- Kevin Clark http://glu.ttono.us From ned.wolpert at gmail.com Thu Apr 12 18:24:40 2007 From: ned.wolpert at gmail.com (Ned Wolpert) Date: Thu, 12 Apr 2007 15:24:40 -0700 Subject: [mocha-developer] Preview of Latest Mocha Changes Message-ID: <461EB1A8.5000402@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 James- My tests have not been broken by the latest updates. Also I have not yet needed to pass blocks around, so I have no 'in-use' response to your two deprecations you want to do. I could see wanting to pass a block in Expectation#with, but can't give a real example. On Expectation#returns, I did see a need to have the return execute a block to return data, but after a few mins I changed my mind. I don't think that I'd want to do this in the future, especially after I talked myself out of doing it the first time. I do like the other features you've given, especially the multiple_yields. - -- Virtually, Ned Wolpert ACF63C1E An idea is something you have; an ideology is something that has you. -Morris Berman -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.3 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGHrGo2nkMaKz2PB4RAiuEAKCwsP1n0ItzypD99s1C6oQdQ5719gCfRcio okbPV2ErMAnHqMXBmRPBHOo= =6Ux3 -----END PGP SIGNATURE----- From jamesmead44 at gmail.com Fri Apr 13 00:08:01 2007 From: jamesmead44 at gmail.com (James Mead) Date: Fri, 13 Apr 2007 05:08:01 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <461EB1A8.5000402@gmail.com> References: <461EB1A8.5000402@gmail.com> Message-ID: <1db558f00704122108m1124fa39jd340b73e75c882bd@mail.gmail.com> Thanks for the helpful & positive feedback, Ned. -- James. http://blog.floehopper.org From dan at tastapod.com Sat Apr 14 15:10:32 2007 From: dan at tastapod.com (Dan North) Date: Sat, 14 Apr 2007 20:10:32 +0100 Subject: [mocha-developer] Feature request... I think... In-Reply-To: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> References: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> Message-ID: <46212728.5020901@tastapod.com> You could try something like this: def test_check_state_of_b class B alias :original_do_something :do_something def do_something(*args) # pre-checks here original_do_something(*args) # post-checks here end end # body of test here class B alias :do_something :original_do_something end end It's evil, but it works. In fact if you inject the instance of b into a, you could just doctor the specific instance of b rather than the whole B class. Cheers, Dan Ned Wolpert wrote: > Folks- > > I just started using Mocha and I wanted to try something but I > couldn't get it to work. I'm coming from the Java world, so my > approach may not be optimal for Ruby. > > Say I'm testing a.do_something() which calls b.do_other_thing() twice, > but I really don't want to change b.do_other_thing(), just 'expect' it > to be called twice. I know I can b.expect(:do_other_thing).times(2) > but it changes the whole method. Unless I'm doing something wrong, I > can't do this in mocha. > > I know its not mocking the object or method. But what I really want > to do is put in a hook into validate the state of the object at the > point of time into and out of the method. If this isn't the place of > mocha, where should I do it? > > (And yes, one can easily argue that I'm likely making my test case too > complicated if I have to do this, but we found an esoteric bug on a > short-lived object and having a test to check for this specific case > would help make sure that bug stays away.) > > From cohen.jeff at gmail.com Sat Apr 14 19:29:20 2007 From: cohen.jeff at gmail.com (Jeff Cohen) Date: Sat, 14 Apr 2007 18:29:20 -0500 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> Message-ID: <3d7e01550704141629g29cdeda4s4bec2e8cd65d7820@mail.gmail.com> On 4/12/07, Kevin Clark wrote: > > This looks awesome James. I now wish I'd submitted a Railsconf talk > about mocha instead of heckle (no love for the heckle these days :( ). > It just gets better and better. > Is it really too late? :-) I'll be at RailsConf and would love to see a good Mocha presentation. Jeff From kevin.clark at gmail.com Sat Apr 14 19:49:14 2007 From: kevin.clark at gmail.com (Kevin Clark) Date: Sat, 14 Apr 2007 16:49:14 -0700 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: <3d7e01550704141629g29cdeda4s4bec2e8cd65d7820@mail.gmail.com> References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> <3d7e01550704141629g29cdeda4s4bec2e8cd65d7820@mail.gmail.com> Message-ID: Jeff, Fraid so, but I'll see if I can't get some sort of video podcast going to show off the latest goodies. Kev On 4/14/07, Jeff Cohen wrote: > On 4/12/07, Kevin Clark wrote: > > > > This looks awesome James. I now wish I'd submitted a Railsconf talk > > about mocha instead of heckle (no love for the heckle these days :( ). > > It just gets better and better. > > > > Is it really too late? :-) I'll be at RailsConf and would love to see a > good Mocha presentation. > > Jeff > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > -- Kevin Clark http://glu.ttono.us From ned.wolpert at gmail.com Sun Apr 15 17:22:04 2007 From: ned.wolpert at gmail.com (Ned Wolpert) Date: Sun, 15 Apr 2007 14:22:04 -0700 Subject: [mocha-developer] Feature request... I think... In-Reply-To: <46212728.5020901@tastapod.com> References: <33cb339b0704111356o33805162pa0955dfb6a79e295@mail.gmail.com> <46212728.5020901@tastapod.com> Message-ID: <33cb339b0704151422u1b1c7d98m5b2d96d136ed78f0@mail.gmail.com> Yeah, that's true. What I really want is c.proxy(:do_something).times(2) as a way of calling something that did what you mention below. It wouldn't be hard to whip up... I just thought it made sense to have it in Mocha... though I do understand its not 'mocking objects'. On 4/14/07, Dan North wrote: > You could try something like this: > > def test_check_state_of_b > class B > alias :original_do_something :do_something > def do_something(*args) > # pre-checks here > original_do_something(*args) > # post-checks here > end > end > > # body of test here > > class B > alias :do_something :original_do_something > end > end > > It's evil, but it works. In fact if you inject the instance of b into a, > you could just doctor the specific instance of b rather than the whole B > class. > > Cheers, > Dan > > > Ned Wolpert wrote: > > Folks- > > > > I just started using Mocha and I wanted to try something but I > > couldn't get it to work. I'm coming from the Java world, so my > > approach may not be optimal for Ruby. > > > > Say I'm testing a.do_something() which calls b.do_other_thing() twice, > > but I really don't want to change b.do_other_thing(), just 'expect' it > > to be called twice. I know I can b.expect(:do_other_thing).times(2) > > but it changes the whole method. Unless I'm doing something wrong, I > > can't do this in mocha. > > > > I know its not mocking the object or method. But what I really want > > to do is put in a hook into validate the state of the object at the > > point of time into and out of the method. If this isn't the place of > > mocha, where should I do it? > > > > (And yes, one can easily argue that I'm likely making my test case too > > complicated if I have to do this, but we found an esoteric bug on a > > short-lived object and having a test to check for this specific case > > would help make sure that bug stays away.) > > > > > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > -- Virtually, Ned Wolpert "Settle thy studies, Faustus, and begin..." --Marlowe Discere docendo... From cohen.jeff at gmail.com Sun Apr 15 20:05:01 2007 From: cohen.jeff at gmail.com (Jeff Cohen) Date: Sun, 15 Apr 2007 19:05:01 -0500 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> <3d7e01550704141629g29cdeda4s4bec2e8cd65d7820@mail.gmail.com> Message-ID: <3d7e01550704151705g7da4f36bm5b7a241d2b795673@mail.gmail.com> On 4/14/07, Kevin Clark wrote: > > Jeff, > Fraid so, but I'll see if I can't get some sort of video podcast going > to show off the latest goodies. > That would be great. Thanks! Jeff From jamesthepiper at gmail.com Wed Apr 18 14:33:46 2007 From: jamesthepiper at gmail.com (James Moore) Date: Wed, 18 Apr 2007 11:33:46 -0700 Subject: [mocha-developer] Automatically mocking ActiveRecord methods In-Reply-To: References: <7cfed280703181003q2ac0a225v676f0aae214f3ad0@mail.gmail.com> <1db558f00703270701l3f35d334ved9e3f62fb13fce0@mail.gmail.com> <7cfed280704020924o347d9824g461c935abf6f4053@mail.gmail.com> Message-ID: <7cfed280704181133h7dfa781dh88db0fe0263c3f35@mail.gmail.com> On 4/2/07, Frederick Cheung wrote: > > > On 2 Apr 2007, at 17:24, James Moore wrote: > > > > > I'm now wondering whether a better way to do this is to add a > > facility to > > add callbacks that can create mocks and stubs when a particular > > object is > > instantiated from the database. A sort of cleanup method on Rails > > find*() > > methods that will allow you to do mock/stub methods on an object > > with a > > particular id (or some set of criteria) when it's created. > > I did this via the after_find callback a few weeks ago. I posted my > code here when I did it maybe you'll find some inspiration there ? > > Fred > Thanks Fred - I took a look, and here's what I'm currently playing with. First, I tried doing just a mock of the WhateverRecord.expects(:find).with(32).returns(my_mocked_obj). The problem there was that Rails doesn't always just do a find with an id; when you've got relations and validations, you'll get finds that specify more than just the id itself. What does get called every time, with the things you want arranged in a nice convenient package, is #instantiate. It's the method that turns the data for the row into an object, and it's primary purpose in life is to support STI. So I hijacked it, and now am using something that looks like this: Annotation.send :include, MockActiveRecord foo = Foo.new :whatever => 'blah' foo.expects(:snark).with(999) Foo.mock_active_record(foo.id => foo) Every time a record of class Foo is created, the id is checked to see if it matches an id passed to mock_active_record(). If there's a match, that object is returned, otherwise the normal #instantiate is called to build a new object. Here's the current (experimental) code: # Adds mock_active_record to an ActiveRecord class. # # Any time an ActiveRecord object is instantiated, # its id will be checked against a list of mocked # ids. If the new object is present in that list, # use the mock instead of the object produced # by ActiveRecord. # # Example: # # class FooTest < Test::Unit::TestCase # def test_foo # Foo.send :include, MockActiveRecord # # # Create a new Foo in the database # f = Foo.create :msg => 'blah' # # # Add a stub that will be used # # in place of the Foo that was just # # created. # Foo.mock_active_record(f.id => stub(:msg => :abc)) # # # find() will match the stub instead # # of the record from the database. # # f = Foo.find(f.id) # assert_equal :abc, f.msg # end # end module InterceptMethod def self.included target target.extend ClassMethods end module ClassMethods def intercept_method call_name, &block unbound_method = instance_method call_name define_method call_name do |*args| bound_method = unbound_method.bind(self) block.call(bound_method, *args) end end def intercept_class_method call_name, &block class_method = method call_name s = class << self; self; end s.send :define_method, call_name do |*args| block.call(class_method, *args) end end end end module MockActiveRecord # Classes that include MockActiveRecord # get: # # - an overridden instantiate() # - mock_active_record() def self.included target target.class_eval do include InterceptMethod extend ClassMethods intercept_class_method :instantiate do |method_obj, *args| mocked_record_match?(*args) || method_obj.call(*args) end end end module ClassMethods def mock_active_record ids_to_mocks ids_to_mocks.each_pair do |k, v| mocked_record_store k, v end end protected def mocked_record_match? record @@mocked_records ||= {} return @@mocked_records[record['id'].to_i] end def mocked_record_store k, v @@mocked_records ||= {} @@mocked_records[k.to_i] = v end end end From jamesthepiper at gmail.com Wed Apr 18 14:35:55 2007 From: jamesthepiper at gmail.com (James Moore) Date: Wed, 18 Apr 2007 11:35:55 -0700 Subject: [mocha-developer] Automatically mocking ActiveRecord methods In-Reply-To: <7cfed280704181133h7dfa781dh88db0fe0263c3f35@mail.gmail.com> References: <7cfed280703181003q2ac0a225v676f0aae214f3ad0@mail.gmail.com> <1db558f00703270701l3f35d334ved9e3f62fb13fce0@mail.gmail.com> <7cfed280704020924o347d9824g461c935abf6f4053@mail.gmail.com> <7cfed280704181133h7dfa781dh88db0fe0263c3f35@mail.gmail.com> Message-ID: <7cfed280704181135m45ce6d61n316c425fd810181@mail.gmail.com> On 4/18/07, James Moore wrote: > Annotation.send :include, MockActiveRecord That should be "Foo.send", not "Annotation.send" - James From jamesmead44 at gmail.com Thu Apr 19 12:21:43 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 19 Apr 2007 17:21:43 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> Message-ID: <1db558f00704190921o3e33b5a2h352006b6a872fcdb@mail.gmail.com> On 12/04/07, Kevin Clark wrote: > This looks awesome James. I now wish I'd submitted a Railsconf talk > about mocha instead of heckle (no love for the heckle these days :( ). > It just gets better and better. > > Kevin Clark > http://glu.ttono.us Thanks for the positive feedback. -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Thu Apr 19 12:23:11 2007 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 19 Apr 2007 17:23:11 +0100 Subject: [mocha-developer] Preview of Latest Mocha Changes In-Reply-To: References: <1db558f00704121021n3af7264bxd170bce7cbaae485@mail.gmail.com> <3d7e01550704141629g29cdeda4s4bec2e8cd65d7820@mail.gmail.com> Message-ID: <1db558f00704190923l5e85f4b8u8c7fe9faebb38197@mail.gmail.com> On 15/04/07, Kevin Clark wrote: > Jeff, > Fraid so, but I'll see if I can't get some sort of video podcast going > to show off the latest goodies. > > Kev > -- > Kevin Clark > http://glu.ttono.us Cool. Let me know if I can help :-) -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Wed Apr 25 12:33:49 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 25 Apr 2007 17:33:49 +0100 Subject: [mocha-developer] mocking missing methods In-Reply-To: <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> Message-ID: <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> Hi Dan, David, and any other interested parties, I've just been looking into implementing this and have come up with a few issues. It'd be great to have some feedback. In Dan's sheep example, you want to constrain the mock to only respond like an instance of the Sheep class. For completeness I think we should allow you to constrain the mock to only respond like the Sheep class itself. I've been playing with some possible syntax... sheep = mock() sheep.responds_like(instance_of(Sheep)) sheep_class = mock sheep_class.responds_like(Sheep) As you can see I'm also inclined to avoid overloading the parameters of the mock() method any more - hence the responds_like() method. What do you think about the instance_of() method? What do you think about the responds_like() method? I like Dan's idea of raising a NoMethodError at invoke time, but I'm wondering if I should extend the message slightly to avoid confusion if you've actually set up an expectation for the non-existent method... sheep = mock() sheep.responds_like(instance_of(Sheep)) sheep.expects(:foo).with(:bar) sheep.foo # => NoMethodError: undefined method `foo' for # which responds like instance_of(Sheep) What do you think about the extension to the exception message: "which responds like instance_of(Sheep)"? -- James. http://blog.floehopper.org From dchelimsky at gmail.com Wed Apr 25 17:29:01 2007 From: dchelimsky at gmail.com (David Chelimsky) Date: Wed, 25 Apr 2007 17:29:01 -0400 Subject: [mocha-developer] mocking missing methods In-Reply-To: <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> Message-ID: <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> On 4/25/07, James Mead wrote: > Hi Dan, David, and any other interested parties, > > I've just been looking into implementing this and have come up with a > few issues. It'd be great to have some feedback. > > In Dan's sheep example, you want to constrain the mock to only respond > like an instance of the Sheep class. For completeness I think we > should allow you to constrain the mock to only respond like the Sheep > class itself. I've been playing with some possible syntax... > > sheep = mock() > sheep.responds_like(instance_of(Sheep)) > > sheep_class = mock > sheep_class.responds_like(Sheep) How about .... sheep = mock() sheep.responds_like(Sheep) sheep_class = mock sheep_class.responds_like(Sheep.class) > > As you can see I'm also inclined to avoid overloading the parameters > of the mock() method any more - hence the responds_like() method. > > What do you think about the instance_of() method? > What do you think about the responds_like() method? > > I like Dan's idea of raising a NoMethodError at invoke time, but I'm > wondering if I should extend the message slightly to avoid confusion > if you've actually set up an expectation for the non-existent > method... > > sheep = mock() > sheep.responds_like(instance_of(Sheep)) > sheep.expects(:foo).with(:bar) > sheep.foo # => NoMethodError: undefined method `foo' for > # which responds like instance_of(Sheep) > > What do you think about the extension to the exception message: "which > responds like instance_of(Sheep)"? Based on my suggestion above, I'd like "which responds like Sheep" or "which response like Sheep.class". This is all just a matter of detail and style. However it lands, I do like the overall idea of having #responds_like and having support for classes and instances. The suggestion I'm making seems to align more w/ the notion of "class as object" (i.e. we're either dealing w/ an instance of Sheep or an instance of Sheep.class - but either way we're talking about how an instance of something behaves). WDYT? Cheers, David > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From jamesmead44 at gmail.com Wed Apr 25 18:03:34 2007 From: jamesmead44 at gmail.com (James Mead) Date: Wed, 25 Apr 2007 23:03:34 +0100 Subject: [mocha-developer] mocking missing methods In-Reply-To: <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> Message-ID: <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> Hmm. Interesting. I think I find my examples more readable/logical than the ones you give, but it's helpful to have someone else's take on the matter. Also wouldn't there be difficulties implementing the responds_like(Sheep.class) version, in that the class() method on any class object will return Class e.g. Sheep.class # => Class and Goat.class # => Class. An example I forgot to mention... sheep = mock() sheep.responds_like(Sheep.new) So responds_like(responder) just needs a responder that responds to respond_to?() if you see what I mean. The instance_of() method would be provided so you didn't have to construct an instance of an object just so you could mock it. -- James. http://blog.floehopper.org From dchelimsky at gmail.com Wed Apr 25 19:19:50 2007 From: dchelimsky at gmail.com (David Chelimsky) Date: Wed, 25 Apr 2007 19:19:50 -0400 Subject: [mocha-developer] mocking missing methods In-Reply-To: <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> Message-ID: <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> On 4/25/07, James Mead wrote: > Hmm. Interesting. I think I find my examples more readable/logical > than the ones you give, but it's helpful to have someone else's take > on the matter. > > Also wouldn't there be difficulties implementing the > responds_like(Sheep.class) version, in that the class() method on any > class object will return Class e.g. Sheep.class # => Class and > Goat.class # => Class. Bummer - was just thinking about the outside view - this does present a problem. > > An example I forgot to mention... > > sheep = mock() > sheep.responds_like(Sheep.new) > > So responds_like(responder) just needs a responder that responds to > respond_to?() if you see what I mean. The instance_of() method would > be provided so you didn't have to construct an instance of an object > just so you could mock it. I think the thing that led me to Sheep/Sheep.class is the lack of symmetry that instance_of(Sheep) introduces. I guess I'd rather have the instance be the default and have a special way to indicate that I'm interested in class methods: sheep = mock() sheep.responds_like(Sheep) sheep_class = mock sheep_class.responds_like(class_of(Sheep)) I don't like #class_of, but you get the idea. How about this? sheep = mock() sheep.responds_like(Sheep, :instance) sheep_class = mock sheep_class.responds_like(Sheep, :class) ... and have :instance be the default so you can say responds_like(Sheep) for instances????? Or this? sheep = mock() sheep.responds_like(Sheep) sheep_class = mock sheep_class.responds_like_class(Sheep) Actually, I think this would be the easiest to implement, too. #responds_like(klass) could ask for klass's public_instance_methods and #responds_like_class(klass) could ask for klass's public_class_methods. If, on the other hand, supporting instance_of(Sheep), responds_like(responder) has to treat responder differently if it is (instance_of(Sheep)) or just (Sheep). In the case of just Sheep, it could ask for it's public_class_methods. In the case of instance_of(Sheep) it would have to ask for something else - or you'd have to override public_class_methods on the object returned by instance_of(Sheep) to return the sheep's public_instance_methods - which just doesn't seem right to me. WDYT? David > > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From ned.wolpert at gmail.com Thu Apr 26 01:54:56 2007 From: ned.wolpert at gmail.com (Ned Wolpert) Date: Wed, 25 Apr 2007 22:54:56 -0700 Subject: [mocha-developer] mocking missing methods In-Reply-To: <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> Message-ID: <33cb339b0704252254g340bc61mdd5a50dd6b4aacbf@mail.gmail.com> If I had a vote, I'd vote for this one... sheep.responds_like(Sheep, :instance) sheep_class.responds_like(Sheep, :class) On 4/25/07, David Chelimsky wrote: > On 4/25/07, James Mead wrote: > > Hmm. Interesting. I think I find my examples more readable/logical > > than the ones you give, but it's helpful to have someone else's take > > on the matter. > > > > Also wouldn't there be difficulties implementing the > > responds_like(Sheep.class) version, in that the class() method on any > > class object will return Class e.g. Sheep.class # => Class and > > Goat.class # => Class. > > Bummer - was just thinking about the outside view - this does present a problem. > > > > > An example I forgot to mention... > > > > sheep = mock() > > sheep.responds_like(Sheep.new) > > > > So responds_like(responder) just needs a responder that responds to > > respond_to?() if you see what I mean. The instance_of() method would > > be provided so you didn't have to construct an instance of an object > > just so you could mock it. > > I think the thing that led me to Sheep/Sheep.class is the lack of > symmetry that instance_of(Sheep) introduces. I guess I'd rather have > the instance be the default and have a special way to indicate that > I'm interested in class methods: > > sheep = mock() > sheep.responds_like(Sheep) > > sheep_class = mock > sheep_class.responds_like(class_of(Sheep)) > > I don't like #class_of, but you get the idea. > > How about this? > > sheep = mock() > sheep.responds_like(Sheep, :instance) > > sheep_class = mock > sheep_class.responds_like(Sheep, :class) > > ... and have :instance be the default so you can say > responds_like(Sheep) for instances????? > > Or this? > > sheep = mock() > sheep.responds_like(Sheep) > > sheep_class = mock > sheep_class.responds_like_class(Sheep) > > Actually, I think this would be the easiest to implement, too. > #responds_like(klass) could ask for klass's public_instance_methods > and #responds_like_class(klass) could ask for klass's > public_class_methods. > > If, on the other hand, supporting instance_of(Sheep), > responds_like(responder) has to treat responder differently if it is > (instance_of(Sheep)) or just (Sheep). In the case of just Sheep, it > could ask for it's public_class_methods. In the case of > instance_of(Sheep) it would have to ask for something else - or you'd > have to override public_class_methods on the object returned by > instance_of(Sheep) to return the sheep's public_instance_methods - > which just doesn't seem right to me. > > WDYT? > > David > > > > -- > > James. > > http://blog.floehopper.org > > _______________________________________________ > > mocha-developer mailing list > > mocha-developer at rubyforge.org > > http://rubyforge.org/mailman/listinfo/mocha-developer > > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > -- Virtually, Ned Wolpert "Settle thy studies, Faustus, and begin..." --Marlowe Discere docendo... From jay at jayfields.com Fri Apr 27 17:20:27 2007 From: jay at jayfields.com (Jay Fields) Date: Fri, 27 Apr 2007 17:20:27 -0400 Subject: [mocha-developer] mocking missing methods In-Reply-To: <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> Message-ID: <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> > In the case of just Sheep, it > could ask for it's public_class_methods. In the case of > instance_of(Sheep) it would have to ask for something else - or you'd > have to override public_class_methods on the object returned by > instance_of(Sheep) to return the sheep's public_instance_methods - > which just doesn't seem right to me. How about: # instance methods sheep = mock sheep.restricted_to Sheep.instance_methods or # class methods sheep = mock sheep.restricted_to Sheep.singleton_methods It's a bit more verbose, but more readable in my opinion. Also, I'm not sold on responds_to or restricted_to. I don't find that either one conveys the intent I'm looking for. Thoughts? Jay From dchelimsky at gmail.com Fri Apr 27 19:20:04 2007 From: dchelimsky at gmail.com (David Chelimsky) Date: Fri, 27 Apr 2007 19:20:04 -0400 Subject: [mocha-developer] mocking missing methods In-Reply-To: <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> Message-ID: <57c63afe0704271620p610a8d63n2cdc4f3a7ca266ba@mail.gmail.com> On 4/27/07, Jay Fields wrote: > > In the case of just Sheep, it > > could ask for it's public_class_methods. In the case of > > instance_of(Sheep) it would have to ask for something else - or you'd > > have to override public_class_methods on the object returned by > > instance_of(Sheep) to return the sheep's public_instance_methods - > > which just doesn't seem right to me. > > How about: > > # instance methods > sheep = mock > sheep.restricted_to Sheep.instance_methods > > or > > # class methods > sheep = mock > sheep.restricted_to Sheep.singleton_methods > > It's a bit more verbose, but more readable in my opinion. Also, I'm > not sold on responds_to or restricted_to. I don't find that either > one conveys the intent I'm looking for. > > Thoughts? I love the syntax, though I'd make it a command rather than a "state"-ment: # instance methods sheep = mock sheep.restrict_to Sheep.instance_methods # class methods sheep = mock sheep.restrict_to Sheep.singleton_methods The other problem is related to Dan's initial point about classes that are extended or modified at runtime. If you just pass an Array to #restrict_to then it has no knowledge of the type we're interested in, so methods added downstream wouldn't be discoverable. With that in mind, I propose: # instance methods sheep = mock sheep.restrict_to Sheep, :instance_methods # class methods sheep = mock sheep.restrict_to Sheep, :singleton_methods That keeps the readability Jay proposes and supports the late binding we're looking for. More thoughts? From jamesmead44 at gmail.com Mon Apr 30 14:04:47 2007 From: jamesmead44 at gmail.com (James Mead) Date: Mon, 30 Apr 2007 19:04:47 +0100 Subject: [mocha-developer] mocking missing methods In-Reply-To: <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> Message-ID: <1db558f00704301104s7652f4b9l7c829eaa03679e8@mail.gmail.com> On 27/04/07, Jay Fields wrote: > > How about: > > # instance methods > sheep = mock > sheep.restricted_to Sheep.instance_methods > > or > > # class methods > sheep = mock > sheep.restricted_to Sheep.singleton_methods > > It's a bit more verbose, but more readable in my opinion. Also, I'm > not sold on responds_to or restricted_to. I don't find that either > one conveys the intent I'm looking for. > I was suggesting "responds_like", not "responds_to" or "restricted_to". I don't think the #instance_methods & #singleton_methods style is quite right. e.g. what if #method_missing accepts method names matching a particular pattern. In this case #respond_to? should return true for any method names that #method_missing would handle, but there is no equivalent requirement for #instance_methods to include all matching method names (in fact this list could theoretically be infinite). An obvious example of this would be ActiveRecord's find_by_xxx_and_yyy type methods. It's not a great example, because when I last checked ActiveRecord didn't implement #respond_to? correctly, but that could be fixed! So I think #respond_to? is the right method to be querying. Does this make sense? If not, can you put your finger on what exactly it is you don't like? Here are some fuller examples that may make things clearer... class Sheep def chew(food); end def self.number_of_legs; 4 end end sheep = mock() sheep.responds_like(Sheep.new) assert sheep.respond_to?(:chew) sheep.expects(:chew).with('grass') sheep.chew('grass') sheep_class = mock sheep_class.responds_like(Sheep) assert sheep_class.respond_to?(Sheep) sheep_class.stubs(:number_of_legs).returns(2) assert_equal 2, sheep_class.number_of_legs If constructing a Sheep instance in the test is undesirable, use the #instance_of method... sheep = mock() sheep.responds_like(instance_of(Sheep)) assert sheep.respond_to?(:chew) sheep.expects(:chew).with('grass') sheep.chew('grass') This last example is the one I'm least happy with, especially as it may well be the most common scenario. Any more ideas? Thanks. -- James. http://blog.floehopper.org From jamesmead44 at gmail.com Mon Apr 30 15:37:13 2007 From: jamesmead44 at gmail.com (James Mead) Date: Mon, 30 Apr 2007 20:37:13 +0100 Subject: [mocha-developer] mocking missing methods In-Reply-To: <57c63afe0704271620p610a8d63n2cdc4f3a7ca266ba@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> <57c63afe0704271620p610a8d63n2cdc4f3a7ca266ba@mail.gmail.com> Message-ID: <1db558f00704301237j1be9d1bdteddb4d5bda7cd62c@mail.gmail.com> On 28/04/07, David Chelimsky wrote: > > I love the syntax, though I'd make it a command rather than a > "state"-ment: > > # instance methods > sheep = mock > sheep.restrict_to Sheep.instance_methods > > # class methods > sheep = mock > sheep.restrict_to Sheep.singleton_methods > > The other problem is related to Dan's initial point about classes that > are extended or modified at runtime. If you just pass an Array to > #restrict_to then it has no knowledge of the type we're interested in, > so methods added downstream wouldn't be discoverable. With that in > mind, I propose: > > # instance methods > sheep = mock > sheep.restrict_to Sheep, :instance_methods > > # class methods > sheep = mock > sheep.restrict_to Sheep, :singleton_methods > > That keeps the readability Jay proposes and supports the late binding > we're looking for. > > More thoughts? > As I explained in my reply to Jay's email, I think #respond_to? is the better method to think about than any of the method-listing methods like #instance_methods. I know your last suggestion doesn't actually use those method-listing methods, but it does use that terminology which I think I'd like to avoid. Do you see what I'm getting at? -- James. http://blog.floehopper.org From dan at tastapod.com Mon Apr 30 18:21:37 2007 From: dan at tastapod.com (Dan North) Date: Mon, 30 Apr 2007 23:21:37 +0100 Subject: [mocha-developer] mocking missing methods In-Reply-To: <57c63afe0704271620p610a8d63n2cdc4f3a7ca266ba@mail.gmail.com> References: <45ED45B1.2030102@tastapod.com> <1db558f00703070214g10d9c286rf6e12562c6c8bda@mail.gmail.com> <1db558f00704250933j3a1a8532u62d3bb6e9b5a34b2@mail.gmail.com> <57c63afe0704251429q4f3a1008l70a63e4129537072@mail.gmail.com> <1db558f00704251503n4736efc9h7a833f6607fadb2b@mail.gmail.com> <57c63afe0704251619n62d43621rbff8a5f48209b0f8@mail.gmail.com> <4AB9CF7E-2EBC-4A70-B571-58AEEFF7F286@jayfields.com> <57c63afe0704271620p610a8d63n2cdc4f3a7ca266ba@mail.gmail.com> Message-ID: <46366BF1.8080209@tastapod.com> This is timely for me. I've been thinking about exactly this vocabulary recently, but in the context of BDD rather than (as well as?) mocking. It's about the terms "is a" and "has a" and how they restrict your thinking because they don't really cover the idea of roles. You need "acts like a" or "behaves like a" to really describe multiple hats. In this instance, I would like something like "acts like a" (in fact, David and I were discussing "quacks_like" in another conversation). Here's some thinking-out-loud: So: mock_sheep.responds_like(Sheep.new) or mock_sheep.acts_like(Sheep.new) This should be additive: mock_ninja_sheep.acts_like(Sheep.new) mock_ninja_sheep.acts_like(Ninja.new) or even: mock_ninja_sheep.acts_like(Sheep.new, Ninja.new) One problem I see is a hard-to-detect semantic error: mock_sheep.acts_like(Sheep) # oops - meant Sheep.new Also, what about modules? This is fugly: mock_countable_sheep.acts_like(Sheep.new.extend(Enumerable)) # yuk So, we need a way of saying: "fail intuitively if the mocked object wouldn't respond to this call". Ok, end of ramble. Here's my ill-thought-out proposal: mock_sheep = mock("sheep") # give it a name mock_sheep.responds_like_type(Sheep, ...) # uses #instance_method mock_sheep.responds_like_instance(ninja, ...) # uses #respond_to? mock_sheep.responds_like(cheese) # depends if cheese is class/module The responds_like_type version could even check if type implements method_missing. The failure mode here would be if you wanted to mock the /instance/ methods of a /class/, using responds_like(type), but that seems very much like an edge case, and you could explicitly use responds_like_instance(type) anyway. Of course, all these checks would be done at method invocation time, so late binding would work. Thoughts? David Chelimsky wrote: > On 4/27/07, Jay Fields wrote: > >>> In the case of just Sheep, it >>> could ask for it's public_class_methods. In the case of >>> instance_of(Sheep) it would have to ask for something else - or you'd >>> have to override public_class_methods on the object returned by >>> instance_of(Sheep) to return the sheep's public_instance_methods - >>> which just doesn't seem right to me. >>> >> How about: >> >> # instance methods >> sheep = mock >> sheep.restricted_to Sheep.instance_methods >> >> or >> >> # class methods >> sheep = mock >> sheep.restricted_to Sheep.singleton_methods >> >> It's a bit more verbose, but more readable in my opinion. Also, I'm >> not sold on responds_to or restricted_to. I don't find that either >> one conveys the intent I'm looking for. >> >> Thoughts? >> > > I love the syntax, though I'd make it a command rather than a "state"-ment: > > # instance methods > sheep = mock > sheep.restrict_to Sheep.instance_methods > > # class methods > sheep = mock > sheep.restrict_to Sheep.singleton_methods > > The other problem is related to Dan's initial point about classes that > are extended or modified at runtime. If you just pass an Array to > #restrict_to then it has no knowledge of the type we're interested in, > so methods added downstream wouldn't be discoverable. With that in > mind, I propose: > > # instance methods > sheep = mock > sheep.restrict_to Sheep, :instance_methods > > # class methods > sheep = mock > sheep.restrict_to Sheep, :singleton_methods > > That keeps the readability Jay proposes and supports the late binding > we're looking for. > > More thoughts? > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >