James Mead
2007-Nov-13 13:18 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
On 13/11/2007, Pradeep Gatram <pradeep.gatram at gmail.com> wrote:> > Let me put my dilemma as an example. Take a look at a snippet from > FooTest. > > #using mocha > def test_method1 > Bar.expects(:method2).with(''param1'', ''param2'').once > Foo.method1 > end > > And now the implementation > > class Foo > def self.method1 > Bar.method2(''param1'', ''param2'') > end > end > > class Bar > end > > So far so good... Now my dilemma is that while implementing method2 in > Bar, I can come up with any weird signature (e.g. def method2 > someInteger, someOtherNumber) and I will not be breaking FooTest. This > obviously makes life hard while refactoring. Coming from a Java/C# > background, I used to rely on compilation to catch these issues. > > How have people solved such problems? > > PradeepHi Pradeep, Fundamentally you should never rely on only mock based tests, you should always have some functional tests to check all the objects are wired together correctly, but... Mocha [1] used to only allow you to mock *existing* methods on *concrete* classes. This functionality accidentally got removed a while ago, but I''d like to reintroduce it asap. You can already restrict expecations on *mocks* by using the responds_like modifier [2], something like this... class Foo def bar end end def test_me foo = mock(''foo'') foo.responds_like(Foo.new) foo.expects(:not_bar) foo.not_bar end # => NoMethodError: undefined method `not_bar'' for #<Mock:foo> which responds like #<Foo:0x432e5c> -- James. http://blog.floehopper.org http://tumble.floehopper.org [1] http://mocha.rubyforge.org [2] http://mocha.rubyforge.org/classes/Mocha/Mock.html#M000032
David Chelimsky
2007-Nov-13 14:44 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
On Nov 13, 2007 7:18 AM, James Mead <jamesmead44 at gmail.com> wrote:> Mocha [1] used to only allow you to mock *existing* methods on *concrete* > classes. This functionality accidentally got removed a while ago, but I''d > like to reintroduce it asap.I beg of you, please don''t. At least not as a default behaviour. Mocks are very powerful tools for interface discovery (http://www.jmock.org/oopsla2004.pdf). With an enforcement rule like the one you propose reinstating, we''d have to stop working on the object at hand to go write a class and/or method. This would break the flow of the current task, force us to shift focus. Not only do we break the current flow, but by going over to the other object and sticking in a stub to get the mock to shut up, we run a far greater risk of leaving things 1/2 done than we do by sending unsupported messages and have our integration tests expose those holes. For anybody who is serious about doing TDD, this would be a major step backwards. What we''ve talked about adding to ... ahem ... another mocking library, is the ability engage this behaviour explicitly with an environment variable or a command line switch. That would provide the best of both worlds because you could stay focused on the task at hand AND you could get a report of the methods you don''t have on collaborating classes so you know where to go next. I''d strongly recommend that you consider a similar path before simply forcing this rule on mocha users. Cheers, David
Zach Moazeni
2007-Nov-13 14:50 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
+1 on David''s response. -Zach On Nov 13, 2007, at 9:44 AM, David Chelimsky wrote:> On Nov 13, 2007 7:18 AM, James Mead <jamesmead44 at gmail.com> wrote: >> Mocha [1] used to only allow you to mock *existing* methods on >> *concrete* >> classes. This functionality accidentally got removed a while ago, >> but I''d >> like to reintroduce it asap. > > I beg of you, please don''t. At least not as a default behaviour. > > Mocks are very powerful tools for interface discovery > (http://www.jmock.org/oopsla2004.pdf). With an enforcement rule like > the one you propose reinstating, we''d have to stop working on the > object at hand to go write a class and/or method. This would break the > flow of the current task, force us to shift focus. > > Not only do we break the current flow, but by going over to the other > object and sticking in a stub to get the mock to shut up, we run a far > greater risk of leaving things 1/2 done than we do by sending > unsupported messages and have our integration tests expose those > holes. > > For anybody who is serious about doing TDD, this would be a major step > backwards. > > What we''ve talked about adding to ... ahem ... another mocking > library, is the ability engage this behaviour explicitly with an > environment variable or a command line switch. That would provide the > best of both worlds because you could stay focused on the task at hand > AND you could get a report of the methods you don''t have on > collaborating classes so you know where to go next. > > I''d strongly recommend that you consider a similar path before simply > forcing this rule on mocha users. > > Cheers, > David > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer
James Mead
2007-Nov-13 15:54 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
> > On Nov 13, 2007, at 9:44 AM, David Chelimsky wrote: > > I beg of you, please don''t. At least not as a default behaviour. > > > > Mocks are very powerful tools for interface discovery > > (http://www.jmock.org/oopsla2004.pdf). With an enforcement rule like > > the one you propose reinstating, we''d have to stop working on the > > object at hand to go write a class and/or method. This would break the > > flow of the current task, force us to shift focus. > > > > Not only do we break the current flow, but by going over to the other > > object and sticking in a stub to get the mock to shut up, we run a far > > greater risk of leaving things 1/2 done than we do by sending > > unsupported messages and have our integration tests expose those > > holes. > > > > For anybody who is serious about doing TDD, this would be a major step > > backwards. > > > > What we''ve talked about adding to ... ahem ... another mocking > > library, is the ability engage this behaviour explicitly with an > > environment variable or a command line switch. That would provide the > > best of both worlds because you could stay focused on the task at hand > > AND you could get a report of the methods you don''t have on > > collaborating classes so you know where to go next. > > > > I''d strongly recommend that you consider a similar path before simply > > forcing this rule on mocha users. > > > > Cheers, > > David >Don''t panic! I wouldn''t dream of forcing it on anybody - I was envisaging something similar to what you suggest.-- James. http://blog.floehopper.org http://tumble.floehopper.org
David Chelimsky
2007-Nov-13 16:51 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
On Nov 13, 2007 9:54 AM, James Mead <jamesmead44 at gmail.com> wrote:> > On Nov 13, 2007, at 9:44 AM, David Chelimsky wrote: > > > What we''ve talked about adding to ... ahem ... another mocking > > > library, is the ability engage this behaviour explicitly with an > > > environment variable or a command line switch. That would provide the > > > best of both worlds because you could stay focused on the task at hand > > > AND you could get a report of the methods you don''t have on > > > collaborating classes so you know where to go next.> Don''t panic!I''ve read that somewhere before :)> I wouldn''t dream of forcing it on anybody - I was envisaging > something similar to what you suggest.--Great. Thanks! Cheers, David
James Mead
2008-Jan-02 16:03 UTC
[mocha-developer] how to ensure signature compliance while mocking in ruby
On 26/11/2007, Pradeep Gatram <pradeep.gatram at gmail.com> wrote:> Sorry for vanishing for a couple of weeks. I have been using ur > suggested approach of ''responds_like''. Although its a good start, it > still does not give me complete confidence. All it tells me is whether > the method is present or not. It does not guarantee signature > compliance. For e.g., referring back to my example... > > class Bar > def method2 param1 > end > end > > The above implementation of method2 in Bar will cause FooTest to pass > even with responds_like. But the 2 parameter signature is clearly not > supported. > > I agree, an integration test should and will catch this scenario and > will fail. But its not possible to write integration tests for every > scenario. After all, the expected method call could happen under a > convoluted condition. A classic case where, I believe, the unit tests > should be able to give me complete guarantee of the state of code.I don''t think you have to write an integration test for *every* scenario. I would aim to write just enough to give decent coverage of the integration points between classes, probably focussing on common or important business scenarios.> So there does appear to be a need for stricter checking. Leaving the > default behaviour as is, maybe introduce a new method like > mocked_object.strictly_expects(:blah)...I have considered something along these lines. I''ll give it some more thought. I''ve added a feature request on rubyforge [1].> That leads me to another aspect? How about validating the return types > :D. Java/C# again gave me that additional safety net of knowing that the > return types were correct while I was mocking (at least thats what I > remember).Hmm. I''m not sure how you are suggesting this could be achieved. Ruby methods do not declare their return type in the method declaration. I think the best way of obtaining the safety net you describe is to use integration tests. Alternatively you could go back to a statically typed language ;-) -- James. http://blog.floehopper.org http://tumble.floehopper.org [1] http://rubyforge.org/tracker/index.php?func=detail&aid=16769&group_id=1917&atid=7480