在ruby中模拟第三方对象的最佳方法是什么?

spi*_*ock 7 ruby testing rspec mocking

我正在使用twitter gem编写测试应用程序,我想编写集成测试,但我无法弄清楚如何在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
Run Code Online (Sandbox Code Playgroud)

这是我正在尝试编写的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
Run Code Online (Sandbox Code Playgroud)

但是,我收到了这个错误:

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)>'
Run Code Online (Sandbox Code Playgroud)

上面的模拟使用的是rspec,但我也很乐意尝试mocha.任何帮助将不胜感激.

好的,感谢大家的帮助,我设法解决了这个问题.这是最后的测试:

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
Run Code Online (Sandbox Code Playgroud)

诀窍是弄清楚我需要存根:configure:new真实对象和存根:current_user以及:name一个dobuled对象实例.

bke*_*ner 6

我认为问题在于您使用模拟的方式,您创建了模拟@twitter,但您从未真正使用过它。我认为您可能会有这样的印象:对 Twitter 的任何调用都将使用您指定的存根方法,但事实并非如此,只有对 @twitter 的调用才会被存根。

我使用双红宝石,而不是 rspec 模拟,但我相信你想做这样的事情:

Twitter.stub!(:configure).and_return true
...
Twitter::Client.stub!(:current_user).and_return @user
Run Code Online (Sandbox Code Playgroud)

这可以确保无论何时调用您在 Twitter、Twitter::Client 上存根的方法,它们都会按照您想要的方式做出响应。

另外,这似乎很奇怪,这是作为视图的一部分进行测试的,实际上应该是控制器测试的一部分,除非我遗漏了一些东西。