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.