2014-04-14 76 views
13

我之前問過類似的問題,但我想我已經超過了我原來的錯誤。無論如何,我有一個新的樂趣失敗,我正在試圖找出一個爆炸(注意諷刺)。這裏是我的失敗:如何使用Rails,Omniauth和Rspec進行單元測試Facebook登錄操作

1) SessionsController#facebook_login should be valid 
    Failure/Error: get :facebook_login 
    NoMethodError: 
    undefined method `slice' for nil:NilClass 
    # ./app/models/user.rb:19:in `from_omniauth' 
    # ./app/controllers/sessions_controller.rb:22:in `facebook_login' 
    # ./spec/controllers/sessions_controller_spec.rb:96:in `block (3 levels) in <top (required)>' 

sessions_controller_spec.rb

describe '#facebook_login' do 

    before(:each) do 
    valid_facebook_login_setup 
    request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:facebook] 
    get :facebook_login 
    end 

    it "should be valid" do 
    expect(response).to be_success 
    end 

    it "should set user_id" do 
    expect(session[:user_id]).to be_true 
    end 
end 

sessions_controller.rb

def facebook_login 
    if request.env['omniauth.auth'] 
    user = User.from_omniauth(env['omniauth.auth']) 
    session[:user_id] = user.id 
    redirect_back_or root_path 
    else 
    redirect_to root_path 
    end 
end 

omniauth_test_helper.rb

module OmniAuthTestHelper 
    def valid_facebook_login_setup 
    if Rails.env.test? 
     OmniAuth.config.test_mode = true 
     OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new({ 
     provider: 'facebook', 
     uid: '123545', 
     info: { 
      first_name: "Andrea", 
      last_name: "Del Rio", 
      email:  "[email protected]" 
     }, 
     credentials: { 
      token: "123456", 
      expires_at: Time.now + 1.week 
     } 
     }) 
    end 
    end 

    def facebook_login_failure 
    OmniAuth.config.mock_auth[:facebook] = :invalid_credentials 
    end 
end 

spec_helper.rb

RSpec.configure do |config| 
    config.include FactoryGirl::Syntax::Methods 
    config.include Capybara::DSL 
    config.fixture_path = "#{::Rails.root}/spec/fixtures" 
    config.use_transactional_fixtures = true 
    config.infer_base_class_for_anonymous_controllers = false 
    config.order = "random" 
    config.include SessionTestHelper, type: :controller 
    config.include OmniAuthTestHelper, type: :controller 
end 

user.rb

class User < ActiveRecord::Base 

    def self.from_omniauth(auth) 
    where(auth.slice(:provider, :uid)).first_or_create do |user| 
     user.provider = auth.provider 
     user.uid = auth.uid 
     user.first_name = auth.info.first_name 
     user.last_name = auth.info.last_name 
     user.email = auth.info.email 
     user.password = auth.credentials.token 
     user.password_confirmation = auth.credentials.token 
     user.oauth_token = auth.credentials.token 
     user.oauth_expires_at = Time.at(auth.credentials.expires_at) 
    end 
    end 
end 

任何幫助將是非常酷。多謝你們!

+0

你明白了嗎?我有同樣的麻煩。用Rspec測試omniauth。 – mharris7190

+0

不幸的是沒有。我一直有意回過頭來研究它。 omn​​iauth文檔有點給了我一些線索https://github.com/intridea/omniauth/wiki/Integration-Testing – freddyrangel

回答

14

好吧我離開這些測試掛起,但我終於想出了這一點。首先,因爲這是一個回調,它不應該是一個控制器測試。它應該是一個請求規範。所以我們會在給定模擬會登錄一個用戶時測試「/ auth/facebook/callback」。

規格/請求/ user_sessions_request_spec.rb

require 'spec_helper' 

describe "GET '/auth/facebook/callback'" do 

    before(:each) do 
    valid_facebook_login_setup 
    get "auth/facebook/callback" 
    request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:facebook] 
    end 

    it "should set user_id" do 
    expect(session[:user_id]).to eq(User.last.id) 
    end 

    it "should redirect to root" do 
    expect(response).to redirect_to root_path 
    end 
end 

describe "GET '/auth/failure'" do 

    it "should redirect to root" do 
    get "/auth/failure" 
    expect(response).to redirect_to root_path 
    end 
end 

這裏的RSpec的幫手

規格/支持/ omni_auth_test_helper

module OmniAuthTestHelper 
    def valid_facebook_login_setup 
    if Rails.env.test? 
     OmniAuth.config.test_mode = true 
     OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new({ 
     provider: 'facebook', 
     uid: '123545', 
     info: { 
      first_name: "Gaius", 
      last_name: "Baltar", 
      email:  "[email protected]" 
     }, 
     credentials: { 
      token: "123456", 
      expires_at: Time.now + 1.week 
     }, 
     extra: { 
      raw_info: { 
      gender: 'male' 
      } 
     } 
     }) 
    end 
    end 
end 

不要忘了,包括在模塊中的spec_helper

+0

我們如何將這個包含在spec_helper中? – Aleksandrus

+3

@Aleksandrus你可以做一個'require「spec/support/omni_auth_test_helper」'或者你可以添加下面的'Dir [Rails.root.join(「spec/support/**/*。rb」)]。 F |需要f}'這將需要spec/support文件夾下的任何東西 – fatbotdesigns

相關問題