按照 Devise 和 OmniAuth 上的 Railscast,我实现了一个
OmniauthCallbacksController < Devise::OmniauthCallbacksController
,其中包含处理 OmniAuth 回调的单个方法:
def all
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
alias_method :facebook, :all
路线.rb:
devise_for :users, controllers: {omniauth_callbacks: "omniauth_callbacks", :sessions => "sessions" }
我想自定义它,所以我尝试使用 RSpec 来测试它。问题是如何测试这个方法和重定向?
如果在规范中我输入了
user_omniauth_callback_path(:facebook)
,它不会抱怨路线不存在,但似乎并没有实际调用该方法。
根据这个答案“控制器测试使用四个 HTTP 动词(GET、POST、PUT、DELETE),无论您的控制器是否是 RESTful。”我尝试了
get user_...
等,但这里确实抱怨该路线不存在。事实上,如果我这样做 rake routes
,它会显示该路由没有 HTTP 动词:
user_omniauth_callback [BLANK] /users/auth/:action/callback(.:format) omniauth_callbacks#(?-mix:facebook)
你能看到我错过了什么吗?
编辑
所以下面的这个问题调用该方法的一种方式是:
controller.send(:all)
但是我遇到了与提问者遇到的相同错误:
ActionController::RackDelegation#content_type delegated to @_response.content_type, but @_response is nil
您需要做三件事才能完成此任务。
这是一个可能的解决方案,在规范本身中输入 (例如spec/feature/login_spec.rb)。 。 .
let(:current_user) { FactoryGirl.create(:user) }
before do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new({
provider: :facebook,
uid:'12345',
info: {
name: "Joe"
}
})
User.stub(:from_omniauth).and_return(current_user)
end
我根据谷歌身份验证改编了此内容,因此 facebook 可能需要更多字段,但这些是 omniauth 文档需要的唯一字段。您应该能够通过查看数据库架构并查找与文档匹配的字段来找到正确的字段。
就我而言,最小值足以通过请求阶段并进入返回用户的存根方法。此示例还使用了
FactoryGirl。
可能并不完美,但希望对您有所帮助。祝你好运!-丹
rspec 3.4这个例子应该适合你:
describe Users::OmniauthCallbacksController, type: :controller do
let(:current_user) { FactoryGirl.create(:user) }
before do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:your_oauth_provider_here] = OmniAuth::AuthHash.new(
provider: :your_oauth_provider_here,
uid: rand(5**10),
credentials: { token: ENV['CLIENT_ID'], secret: ENV['CLIENT_SECRET'] }
)
request.env['devise.mapping'] = Devise.mappings[:user]
allow(@controller).to receive(:env) { { 'omniauth.auth' => OmniAuth.config.mock_auth[:your_oauth_provider_here] } }
allow(User).to receive(:from_omniauth) { current_user }
end
describe '#your_oauth_provider_here' do
context 'new user' do
before { get :your_oauth_provider_here }
it 'authenticate user' do
expect(warden.authenticated?(:user)).to be_truthy
end
it 'set current_user' do
expect(current_user).not_to be_nil
end
it 'redirect to root_path' do
expect(response).to redirect_to(root_path)
end
end
end
end
RSpec
OmniauthCallbacksController
,对此进行一些研究,它对我有用。这是我的代码,如果有人觉得有必要的话。测试是为了快乐的道路,它应该适用于新闻版本的
RSpec eg. 3.x
require 'spec_helper'
describe OmniauthCallbacksController, type: :controller do
describe "#linkedin" do
let(:current_user) { Fabricate(:user) }
before(:each) do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:linkedin] = OmniAuth::AuthHash.new({provider: :linkedin, uid: '12345', credentials: {token: 'linkedin-token', secret: 'linkedin-secret'}})
request.env["devise.mapping"] = Devise.mappings[:user]
@controller.stub!(:env).and_return({"omniauth.auth" => OmniAuth.config.mock_auth[:linkedin]})
User.stub(:from_auth).and_return(current_user)
end
describe "#linkedin" do
context "with a new linkedin user" do
before { get :linkedin }
it "authenticate user" do
expect(warden.authenticated?(:user)).to be_truthy
end
it "set current_user" do
expect(subject.current_user).not_to be_nil
end
it "redirect to root_path" do
expect(response).to redirect_to(root_path)
end
end
end
end
end
需要“rails_helper”
RSpec.describe Users::OmniauthCallbacksController,类型::controller do 描述“#google_oauth2” 之前做 request.env["devise.mapping"] = Devise.mappings[:user] 结束
context "with valid user" do
let(:role) {Role.create!(name: 'candidate')}
let(:user) {User.create!(email: '[email protected]', password: '123456', role_id: role.id, approved: true)}
let(:auth) do
OmniAuth::AuthHash.new({
provider: 'google_oauth2',
uid: '123456',
info: { email: user.email },
credentials: {
token: 'token',
expires_at: Time.now + 1.hour,
refresh_token: 'refresh_token'
}
})
end
before do
request.env["omniauth.auth"] = auth
end
it "signs in the user and redirects to the root path" do
expect(User).to receive(:from_omniauth).with(auth).and_return(user)
expect(user).to receive(:persisted?).and_return(true)
expect(user).to receive(:save!)
get :google_oauth2
expect(flash[:notice]).to eq(I18n.t("devise.omniauth_callbacks.success", kind: "Google"))
expect(user.access_token).to eq(auth.credentials.token)
expect(user.expires_at.utc.to_s).to eq(auth.credentials.expires_at.utc.to_s)
expect(user.refresh_token).to eq(auth.credentials.refresh_token)
expect(response).to redirect_to(root_path)
end
end
context "with invalid user" do
let(:auth) { OmniAuth::AuthHash.new(provider: 'google_oauth2', uid: 'invalid') }
before do
request.env["omniauth.auth"] = auth
end
it "redirects to the new user registration page" do
expect(User).to receive(:from_omniauth).with(auth).and_return(User.new)
expect_any_instance_of(User).to receive(:persisted?).and_return(false)
get :google_oauth2
expect(session["devise.google_data"]).to eq(request.env["omniauth.auth"])
expect(response).to redirect_to(new_user_registration_url)
end
end
结束
结束