How can I mock the twitter gem?

Hi everyone,

I'm trying to write integration tests for my sample twitter app and I'm having trouble mocking out objects in the Twitter namespace. Here's the function that's giving me trouble:

  def build_twitter(omniauth)     Twitter.configure do |config|       config.consumer_key = TWITTER_KEY       config.consumer_secret = TWITTER_SECRET       config.oauth_token = omniauth['credentials']['token']       config.oauth_token_secret = omniauth['credentials']['secret']     end     client = Twitter::Client.new     user = client.current_user     self.name = user.name   end

and here's the test:

feature 'testing oauth' do   before(:each) do     @twitter = double("Twitter")     @twitter.stub!(:configure).and_return true     @client = double("Twitter::Client")     @client.stub!(:current_user).and_return(@user)     @user = double("Twitter::User")     @user.stub!(:name).and_return("Tester")   end

  scenario 'twitter' do

    visit root_path     login_with_oauth

    page.should have_content("Pages#home")   end end

But, I'm getting this error: Failures:

  1) testing oauth twitter      Failure/Error: login_with_oauth      Twitter::Error::Unauthorized:        GET https://api.twitter.com/1/account/verify_credentials.json: 401: Invalid / expired Token      # ./app/models/user.rb:40:in `build_twitter'      # ./app/models/user.rb:16:in `build_authentication'      # ./app/controllers/authentications_controller.rb:47:in `create'      # ./spec/support/integration_spec_helper.rb:3:in `login_with_oauth'      # ./spec/integration/twit_test.rb:16:in `block (2 levels) in <top (required)>'

Any ideas on how to make this work? I'm using rspec for mocking the objects but I'm open to mocha if that's a better choice.

Thanks, Andrew

Hi everyone,

I'm trying to write integration tests for my sample twitter app and I'm having trouble mocking out objects in the Twitter namespace. Here's the function that's giving me trouble:

def build_twitter(omniauth) Twitter.configure do |config| config.consumer_key = TWITTER_KEY config.consumer_secret = TWITTER_SECRET config.oauth_token = omniauth['credentials']['token'] config.oauth_token_secret = omniauth['credentials']['secret'] end client = Twitter::Client.new user = client.current_user self.name = user.name end

and here's the test:

feature 'testing oauth' do before(:each) do @twitter = double("Twitter") @twitter.stub!(:configure).and_return true @client = double("Twitter::Client") @client.stub!(:current_user).and_return(@user) @user = double("Twitter::User") @user.stub!(:name).and_return("Tester") end

You're creating @twitter, stubbing configure on it and so on, but the code under test is still calling Twitter.configure. Calling double('Twitter') doesn't replace the existing Twitter constant - you need to do something like Twitter.stub(:configure) (or Twitter.should_receive(...), similarly with Twitter::Client.new and so on

Fred

Thank you! I was missing the difference between stubbing a method on the Twitter::Client class vs. instantiating an object via doubling. Once I figured this out, I fixed my tests.