Question

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:

  • client.sitestream is called, with the first 100 Twitter IDs.
  • client.control.add_user() is called with the remaining IDs.

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.)

Was it helpful?

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top