Hello! I'm trying to spec a method, that has several chained calls. http://gist.github.com/78562 (spec) http://gist.github.com/78563 (model) In the first spec, I'm trying to focus on the method calls that have to be made, and the arguments they should receive. Is there a better way to spec the behaviour for these chained calls? It just seems too many lines to me :) Thanks a lot! Levy PS: I'm using my branch of the twitter gem, at http://github.com/levycarneiro/twitter, which just adds this method 'not_retweeted'.
on 2009-03-13 16:08
on 2009-03-13 16:50
You might want to look into using a null object, and breaking that first spec up into several examples (a null object returns itself when sent a message it doesn't know how to handle) http://gist.github.com/78570 I've built more than a few named_scope chains using this pattern, and it seems to work out okay. This approach is somewhat less brittle, in that it's not going to explode horribly if you change the order of the chain in the main method (if something else reads better, say) ... Downside is that it _won't_ catch if you add new methods to the chain. If that's a concern, you could complicate the setup a bit, to narrow the focus to _just_ the methods you want. @new_search = mock(Twitter::Search) new_search.stub!(:containing => new_search, :since => new_search, :not_retweeted => new_search, :fetch => new_search) On Fri, Mar 13, 2009 at 10:04 AM, Levy Carneiro Jr.
on 2009-03-13 17:01
Levy Carneiro Jr. wrote: > Is there a better way to spec the behaviour for these chained calls? > It just seems too many lines to me :) http://c2.com/cgi/wiki?LawOfDemeter Specs are as much of a design tool as a testing tool, and the use of mocks in your specs show just how ugly the current design is. Either write a wrapper around the library which takes care of the method chaining, or write integration tests against it, stubbing out some low level detail of the library. Scott
on 2009-03-14 16:57
Hello Scott, On Fri, Mar 13, 2009 at 11:59 AM, Scott T. <email@example.com>wrote: > http://c2.com/cgi/wiki?LawOfDemeter > > Specs are as much of a design tool as a testing tool, and the use of mocks > in your specs show just how ugly the current design is. > > Either write a wrapper around the library which takes care of the method > chaining, or write integration tests against it, stubbing out some low level > detail of the library. Actually, the method 'fetch_new_tweets' is the wrapper. There's another method called 'process_new_tweets', which calls some methods from the Tweet class, including fetch_new_tweets. But I see your point. Testing only the output from this wrapper (integration tests), and not testing the internal actions being done inside Twitter::Search, which Tweet shouldn't know about. So, the ideal would be the Twitter::Search class to provide some ready-to-use wrappers for me, the way I want it. Like the postman and wallet example . But, since it clearly doesn't have all wrappers I need, shouldn't my own class, Tweets, be doing the several wrappers and testing them on my own? Or, there is a better design pattern in this case?  http://www.ccs.neu.edu/research/demeter/demeter-me... Regards, Levy
on 2009-03-17 13:40
Thanks for your examples, Chris! regards, Levy