Rails rspec and omniauth (integration testing)

2019-04-24 12:14发布

My Rails 3.2 app uses OmniAuth and Devise to sign in with Twitter. The authentication system works fine. I would like to write an integration test in rspec to make sure everything works. Using the information in the wiki, I've written the following, but I know I'm missing things.

Under test.rb in config/environments, I have the following lines

OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:twitter] = {:provider => 'twitter', :uid => '123545'}

My rspec test looks like this:

describe "Authentications" do
  context "without signing into app" do

    it "twitter sign in button should lead to twitter authentication page" do
      visit root_path
      click_link "Sign in with Twitter"
      Authentication.last.uid.should == '123545'
    end

  end
end

Authentication is the name of my model and calling .uid in rails console returns the string fine.

I'm getting the following error when I run this test:

Failure/Error: Authentication.last.uid.should == '123545'
NoMethodError:
undefined method `uid' for nil:NilClass

Can anyone help me figure out how to use the OmniAuth mocks that are provided? An explanation for why and how it works would be appreciated as well.

4条回答
可以哭但决不认输i
2楼-- · 2019-04-24 12:38

I run into something similar.

After changing my mock object from using symbol keys:

OmniAuth.config.mock_auth[:twitter] = {
    :uid => '1337',
    :provider => 'twitter',
    :info => {
      :name => 'JonnieHallman'
    }
  }

to using string keys:

OmniAuth.config.mock_auth[:twitter] = {
    'uid' => '1337',
    'provider' => 'twitter',
    'info' => {
      'name' => 'JonnieHallman'
    }
  }

it worked.

And do you have

  request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter] 

somewhere in your testcase?

查看更多
淡お忘
3楼-- · 2019-04-24 12:38

Did you try moving these two lines to spec_helper.rb?

OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:twitter] = {:provider => 'twitter', :uid => '123545'}

Also add the following before block in your test file:

before do 
    request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter] 
end

You can find more info on this link: https://github.com/intridea/omniauth/wiki/Integration-Testing

查看更多
Summer. ? 凉城
4楼-- · 2019-04-24 12:44

I highly suggest this answer

In short...

  • Set up the mock
  • Make the request
  • Test whatever code is attached to the callback

For example: test the session['uid'] was set (although, I opt to test only what the user sees, or, rather, does not see)

My code...

config/environments/test.rb

Rails.application.configure do
  ...
    OmniAuth.config.test_mode = true
    OmniAuth.config.mock_auth[:linkedin] = { 
      'provider' => 'linkedin', 
      'uid' => '123545', 
      'info'=>
      { 'email'=>'infinite@jest.com',
        'first_name'=>'Dave',
        'last_name'=>'Wallace' }
    }
end

spec/features/sign_in_feature_spec.rb

require 'rails_helper'

feature 'Sign in with LinkedIn' do

  before do 
    OmniAuth.config.add_mock(:linkedin, {:uid => '12345'})
  end

  let(:user) { create(:user) } 

  scenario 'with valid email and password' do
    visit '/'
    expect(page).to have_no_content 'Sign Out'
    click_link 'nav-sign-in' # image/button: Sign in with LinkedIn
    expect(page).to have_content 'Sign Out'
  end
end    

Let me know if/how I may improve this solution (and my code!)

查看更多
时光不老,我们不散
5楼-- · 2019-04-24 13:02

Selected solution does not work for me. My solution i get from https://gist.github.com/kinopyo/1338738 and official doc https://github.com/intridea/omniauth/wiki/Integration-Testing here:

# in spec/support/omniauth_macros.rb
module OmniauthMacros
  def mock_auth_hash
    # The mock_auth configuration allows you to set per-provider (or default)
    # authentication hashes to return during integration testing.
    OmniAuth.config.mock_auth[:odnoklassniki] = OmniAuth::AuthHash.new({
         :provider => 'odnoklassniki',
         :uid => '123545',
         :info => OmniAuth::AuthHash::InfoHash.new({
             :name => 'mockuser'
         })
     })

  end
end

# in spec/spec_helper.rb
RSpec.configure do |config|

  # email spec
  config.include(EmailSpec::Helpers)
  config.include(EmailSpec::Matchers)
end
OmniAuth.config.test_mode = true

# in spec example:
visit new_user_registration_path
mock_auth_hash
find('#btn-odnoklassniki').click # here is link generated as omniauth_authorize_path(resource_name, provider)
查看更多
登录 后发表回答