Как лучше всего издеваться над сторонним объектом в ruby? - PullRequest
7 голосов
/ 29 ноября 2011

Я пишу тестовое приложение, используя драгоценный камень twitter, и я хотел бы написать интеграционный тест, но я не могу понять, как имитировать объекты в пространстве имен Twitter.Вот функция, которую я хочу протестировать:

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

и вот тест rspec, который я пытаюсь написать:

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

Но я получаю эту ошибку:

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

Приведенные выше макеты используют rspec, но я тоже готов попробовать мокко.Любая помощь будет принята с благодарностью.

Хорошо, мне удалось выяснить это благодаря помощи каждого.Вот заключительный тест:

feature 'testing oauth' do
  before(:each) do
    @client = double("Twitter::Client")
    @user = double("Twitter::User")
    Twitter.stub!(:configure).and_return true
    Twitter::Client.stub!(:new).and_return(@client)
    @client.stub!(:current_user).and_return(@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

Хитрость заключалась в том, чтобы выяснить, что мне нужно было заглушить :configure и :new на реальных объектах, а также заглушку :current_user и :name на экземпляре объекта.

Ответы [ 2 ]

4 голосов
/ 30 ноября 2011

Я думаю, проблема в том, как вы используете макет, вы создали макет @twitter, но на самом деле вы его никогда не используете.Я думаю, что у вас может сложиться впечатление, что при любых вызовах в Twitter будут использоваться указанные вами методы-заглушки, но это не совсем так, работают только вызовы, сделанные в @twitter.

Я использую двойной ruby, а не rspecиздевается, но я думаю, что вы хотите сделать что-то вроде этого:

Twitter.stub!(:configure).and_return true
...
Twitter::Client.stub!(:current_user).and_return @user

Это гарантирует, что в любое время вызовы методов, которые вы вставили в Twitter, Twitter :: Client, будут отвечать так, как вы хотите.

Кроме того, кажется странным, что это тестируется как часть представления, а не должно быть частью теста контроллера, если только я что-то не упустил.

0 голосов
/ 29 ноября 2011

Вы можете попробовать что-то вроде http://jondot.github.com/moxy/. Ложные веб-запросы

...