如何使用Google测试身份验证?

时间:2014-02-23 17:19:12

标签: ruby-on-rails ruby testing rspec

我有一个Rails应用程序,其中登录/注销由Devise直接完成。但是,我想允许用户连接他们的Google Adwords帐户(使用https://github.com/googleads/google-api-ads-ruby),因此我有一个控制器负责让用户关联其Google帐户。以下是它的外观:

def callback()
    api = get_adwords_api
    begin
      token = api.authorize(
          {
            :oauth2_callback => adwords_login_callback_url,
            :oauth2_verification_code => params[:code]
          }
      )
      current_user.update_attributes(:adwords_token => token[:access_token], :adwords_refresh_token => token[:refresh_token], :adwords_issued_at => token[:issued_at], :adwords_expires_in => token[:expires_in], :adwords_id_token => token[:id_token])
      flash.notice = 'Authorized successfully'
      redirect_to adwords_home_index_path
    rescue 
      flash.alert = 'Authorization failed'
      redirect_to adwords_login_prompt_path
    end
  end

get_adwords_api看起来像这样:

def create_adwords_api
    config_filename = File.join(Rails.root, 'config', 'adwords_api.yml')
    api = AdwordsApi::Api.new(config_filename) # This is from the GEM
    return api
end

所以,我的问题是:

我应该如何测试用户身份验证是否顺利进行并且模型是否通过回调进行更新?

1 个答案:

答案 0 :(得分:1)

这取决于您的测试理念。我个人会建议不要从功能测试中调用外部服务,并建议使用下面的模拟方法或另一种模拟/存根方法。调用外部服务可能会很慢,受到网络瘫痪(顺便说一下你可以模拟超时等),对于有呼叫配额的服务有问题(在这种情况下可能不适用),等等。因此,对于您的功能测试,您可以模拟服务,以便返回预设信息。通过这种方式,您可以检查您是否正在传递服务敏感信息,并使用您获得的结果做正确的事情。您还可以轻松测试任何错误情况。例如,使用Mocha,您可以在功能测试中执行类似的操作:

api = mock()
canned_auth_response = {:access_token => 'whatever-you-want', :refresh_token => 'blah', :issued_at => 'sometime', :expires_in => 'some-future-time', :id_token => 'some-id'}
api.expects(:authorize).with(has_entries(:oauth2_callback => 'your-url', :oauth2_verification_code => 'whatever-you-put-in-params-code').returns(canned_auth_response)
AdwordsApi::Api.expects(:new).with('your-config-filename').returns(api)

当您的测试调用AdwordsApi::Api.new时,您将返回一个模拟的api对象,它将返回预设的auth_response数据(当然,将其更改为包含适当的数据),这样您就可以了现在调用你的控制器回调,它将使用模拟,然后你可以检查你的回调方法做你期望的。您可以从api模拟中返回错误数据或不完整数据,或者如果在现实生活中可以执行此操作,则可以引发异常。 expects还会检查您是否将所需的参数传递给外部服务。

我不是说这是唯一或最好的方式,或者上述代码保证可以正常工作,但我应该说明这种方法!

如果你真的想要测试真实服务,这是一个很好的冒烟测试/健全性检查,你可以使用vcr gem https://github.com/vcr/vcr来记录/重播http响应(我从来没用过它,但它看起来不错),或者您可以添加仅在特定请求时运行的测试,或者在构建服务器上自动运行。例如,我引用了platformatec的博客文章中的以下内容,该文章表明在rspec中你可以这样做:

describe KittenInfo::Client, external: true do
  # …
end

然后,在spec_helper.rb中,只需设置:

RSpec.configure do |config|
  config.filter_run_excluding external: true
end

现在,默认情况下,运行您的规范将跳过所有具有以下内容的组:external设置为true。无论何时调整客户端或在构建中,都可以使用以下命令运行这些特定的测试:

$ rspec --tag external

有关此rspec方法的完整说明,请参阅http://blog.plataformatec.com.br/2012/10/filtering-examples-in-rspec/