There are a few ways to approach this, depending on what you want to achieve.
If you really want to "expect" rather than "stub", here's one way you
could do it :-
search = Twitter::Search.new # or search = mock('search') if
Twitter::Search.new has any undesirable side-effects
search.expects(:from).with('floehopper').returns(search)
search.expects(:per_page).with(12).returns(search)
Twitter::Search.expects(:new).returns(search)
However, I would counsel against having these expectations setup in
more than one test. Instead, you could do something like this :-
search = stub('search')
search.stubs(:from => search, :per_page => search)
Twitter::Search.stubs(:new).returns(search)
In general, if you're likely to be calling this chain of methods from
a lot of different places in your application and/or in a lot of
tests, I'd be inclined to introduce an adapter class of some sort
which provides a simpler API specific to your application. This will
make mocking easier and tests more readable :-
If you let us know more exactly what invocations you want to "expect"
and what you want to "assert" about them, we can probably give you
more specific advice.
I hope that helps.
Regards, James.
----
http://jamesmead.org/
Something I hadn't noticed previously was that the instance of
Twitter::Search (presumably from John Nunemaker's Twitter gem?)
implements an "each" method and includes Enumerable. This means that
in order to render the view, you probably need to return an object
which supports the relevant methods. One simple way to do this would
be to use a simple Array of tweets. Each tweet seems to be represented
as an instance of a Hashie::Mash, so you could do something like this
:-
twitter_search = [Hashie::Mash.new(:text => "tweet one"),
Hashie::Mash.new(:text => "tweet two")]
twitter_search.stubs(:from).returns(twitter_search)
twitter_search.stubs(:per_page).returns(twitter_search)
Twitter::Search.stubs(:new).returns(twitter_search)
You may need to add other attributes to the Hashie::Mash depending on
what your view requires.
I haven't tested this, but it should allow you to avoid any external
requests to twitter.com.
If you specifically want to "assert" that Twitter::Search#from is
called with the argument "my-username", then you need to introduce a
call to Mocha::Expectation#with along the following lines :-
twitter_search.stubs(:from).with("my-username").returns(twitter_search)
If the Twitter::Search#from method is called with any other argument,
the stubbed method will return nil by default, and the test will
probably fail with a NoMethodError.
I still don't really know enough about precisely what you are trying
to test to give better advice, but hopefully this has helped. If you
want more help, can you post all the code including the ERB template,
and ideally any test code that you have already written.
One last thought would be to find the actual method in the Tweetie gem
that is making the external call to twitter.com. I think it might be
the Twitter::Search#fetch method. You could then just stub this along
the following lines :-
tweets = [Hashie::Mash.new(:text => "tweet one"),
Hashie::Mash.new(:text => "tweet two")]
Twitter::Search.any_instance.stubs(:fetch).returns(tweets)
object.expects(:method).returns(
mock do |method|
expects(:another_method).returns(:chain_result)
end
)
object.method.another_method => :chain_result
Robert Pankowecki
http://robert.pankowecki.pl