rubyrspectweetstream

Using rspec to test a method on an object that's a property of an object


If I have a method like this:

require 'tweetstream'

# client is an instance of TweetStream::Client
# twitter_ids is an array of up to 1000 integers
def add_first_users_to_stream(client, twitter_ids)
    # Add the first 100 ids to sitestream.
    client.sitestream(twitter_ids.slice!(0,100))

    # Add any extra IDs individually.
    twitter_ids.each do |id|
        client.control.add_user(id)
    end

    return client
end

I want to use rspec to test that:

The second point is trickiest for me -- I can't work out how to stub (or whatever) a method on an object that is itself a property of an object.

(I'm using Tweetstream here, although I expect the answer could be more general. If it helps, client.control would be an instance of TweetStream::SiteStreamClient.)

(I'm also not sure a method like my example is best practice, accepting and returning the client object like that, but I've been trying to break my methods down so that they're more testable.)


Solution

  • This is actually a pretty straightforward situation for RSpec. The following will work, as an example:

    describe "add_first_users_to_stream" do
      it "should add ids to client" do
    
        bulk_add_limit = 100
        twitter_ids = (0..bulk_add_limit+rand(50)).collect { rand(4000) }
        extras = twitter_ids[bulk_add_limit..-1]
    
        client = double('client')
        expect(client).to receive(:sitestream).with(twitter_ids[0...bulk_add_limit])
    
        client_control = double('client_control')
        expect(client).to receive(:control).exactly(extras.length).times.and_return(client_control)
        expect(client_control).to receive(:add_user).exactly(extras.length).times.and_return {extras.shift}
    
        add_first_users_to_stream(client, twitter_ids)
    
      end
    end