【问题标题】:How can I access Sorcery in my RSpec tests?如何在我的 RSpec 测试中访问 Sorcery?
【发布时间】:2012-01-03 05:32:14
【问题描述】:

巫术认证宝石:https://github.com/NoamB/sorcery

Sorcery 的创建者提供了一个示例 Rails 应用程序,其 Test::Unit 功能测试中包含 Sorcery 测试助手:https://github.com/NoamB/sorcery-example-app/blob/master/test/functional/users_controller_test.rb

# Test::Unit functional test example
require 'test_helper'

class UsersControllerTest < ActionController::TestCase
  setup do
    @user = users(:noam)
  end

  test "should show user" do
    login_user
    get :show, :id => @user.to_param
    assert_response :success
  end

但我不知道如何让 login_user 在我的 RSpec 控制器规范中工作。

/gems/sorcery-0.7.5/lib/sorcery/test_helpers/rails.rb:7:in `login_user': 
undefined method `auto_login' for nil:NilClass (NoMethodError)

以下是 Sorcery gem 中关于上述错误的相关代码: https://github.com/NoamB/sorcery/blob/master/lib/sorcery/test_helpers/rails.rb

module Sorcery
  module TestHelpers
    module Rails
      # logins a user and calls all callbacks
      def login_user(user = nil)
        user ||= @user
        @controller.send(:auto_login,user)
        @controller.send(:after_login!,user,[user.send(user.sorcery_config.username_attribute_names.first),'secret'])
      end

      def logout_user
        @controller.send(:logout)
      end
    end
  end
end

更新:

根据 Sorcery 的文档“Testing in Rails 3”,我确实已将include Sorcery::TestHelpers::Rails 添加到我的spec_helper.rb

Sorcery 测试助手login_user 作用于@controller,但我收到错误消息,因为在我的控制器规范中@controllernil。这是我的规格:

#spec/controllers/forums_controller_spec.rb
require 'spec_helper'

describe ForumsController do
  render_views

  describe 'GET new' do
    describe 'when guest' do
      it 'should deny and redirect' do
        get :new
        response.should redirect_to(root_path)
      end
    end

    describe 'when admin' do
      p @controller #=> nil
      @user = User.create!(username: "Test", password: "secret", email: "test@test.com")
      login_user # <--------------- where the error occurs
      it 'should resolve' do
        get :new
        response.should render_template(:new)
      end
    end
  end
end

【问题讨论】:

    标签: ruby ruby-on-rails-3 rspec sorcery


    【解决方案1】:

    FWIW,我花了很多时间寻找这个问题的答案。我正在使用 Capybara 和 RSpec。事实证明,您需要手动登录才能使用 Sorcery 登录。

    我在这里创建了一个关于使用 Sorcery/Rspec/Capybara 创建集成测试的要点: https://gist.github.com/2359120/9989c14af19a48ba726240d030c414b882b96a8a

    【讨论】:

    • 好东西。接受了这个答案,而不是我弱小的退出者俱乐部的答案。
    【解决方案2】:

    您需要在您的 spec_helper 中包含 Sorcery 测试助手

        include Sorcery::TestHelpers::Rails
    

    查看魔法维基:https://github.com/NoamB/sorcery/wiki/Testing-rails-3

    在示例 Rails 应用程序中,这是在 https://github.com/NoamB/sorcery-example-app/blob/master/test/test_helper.rb#L13 完成的

    更新

    您在同一文件夹中是否有任何其他控制器规格成功通过? RSpec 通常会在“spec/controllers”文件夹中混合控制器测试所需的东西。

    您可以尝试通过编写明确地将其标记为控制器规范

    describe ForumsController, :type => :controller do
    

    【讨论】:

    • 我更新了我的帖子以反映我已经做出了改变。对,到目前为止我确实做到了。 SOrcery 似乎希望控制器规范中提供@controller@controller 在我的控制器规范中为零。我目前正在查找 RSpec 是否不提供 @controller 或者它是否无法判断我的规范是否是控制器规范。有什么想法吗?
    【解决方案3】:

    您需要将您的用户创建和登录放入 before(:each) 块中,如下所示:

    describe 'when admin' do
      before(:each) do
        @user = User.create!(username: "Test", password: "secret", email: "test@test.com")
        login_user
      end
    
      it 'should resolve' do
        get :new
        response.should render_template(:new)
      end
    end
    

    【讨论】:

      【解决方案4】:

      我自己也刚刚经历过这种困境,并从 danneu、diwalak 和 Birdlevitator 的意见中汲取灵感(在此主题中:rail3/rspec/devise: rspec controller test fails unless I add a dummy=subject.current_user.inspect)我想我可以找到解决方案。

      我一直在使用“rails generate scaffold”命令生成的标准 rails 3 rspec 资源。这是我修改它以使用巫术登录后的控制器 rspec 文件:

      require 'spec_helper'
      
      # This spec was generated by rspec-rails when you ran the scaffold generator.
      # It demonstrates how one might use RSpec to specify the controller code that
      # was generated by Rails when you ran the scaffold generator.
      #
      # It assumes that the implementation code is generated by the rails scaffold
      # generator.  If you are using any extension libraries to generate different
      # controller code, this generated spec may or may not pass.
      #
      # It only uses APIs available in rails and/or rspec-rails.  There are a number
      # of tools you can use to make these specs even more expressive, but we're
      # sticking to rails and rspec-rails APIs to keep things simple and stable.
      #
      # Compared to earlier versions of this generator, there is very limited use of
      # stubs and message expectations in this spec.  Stubs are only used when there
      # is no simpler way to get a handle on the object needed for the example.
      # Message expectations are only used when there is no simpler way to specify
      # that an instance is receiving a specific message.
      
      describe RecordsController do
      
        before(:each) do
          @user = User.create!(forename: "Billy", surname: "Bob", username: "Test", password: "secret!1", email: "test@test.com")
          login_user
        end
      
      
        # This should return the minimal set of attributes required to create a valid
        # Record. As you add validations to Record, be sure to
        # update the return value of this method accordingly.
        def valid_attributes
          { :owner => 'Mr Blobby', :catagory => 'Index'}
        end
      
        # This should return the minimal set of values that should be in the session
        # in order to pass any filters (e.g. authentication) defined in
        # RecordsController. Be sure to keep this updated too.
        def valid_session
          {"warden.user.user.key" => session["warden.user.user.key"]}
        end
      
        describe "GET index" do
          it "assigns all records as @records" do
            record = Record.create! valid_attributes
            get :index, {}, valid_session
            assigns(:records).should eq([record])
          end
        end
      
        describe "GET show" do
          it "assigns the requested record as @record" do
            record = Record.create! valid_attributes
            get :show, {:id => record.to_param}, valid_session
            assigns(:record).should eq(record)
          end
        end
      
        describe "GET new" do
          it "assigns a new record as @record" do
            get :new, {}, valid_session
            assigns(:record).should be_a_new(Record)
          end
        end
      
        describe "GET edit" do
          it "assigns the requested record as @record" do
            record = Record.create! valid_attributes
            get :edit, {:id => record.to_param}, valid_session
            assigns(:record).should eq(record)
          end
        end
      
        describe "POST create" do
          describe "with valid params" do
            it "creates a new Record" do
              expect {
                post :create, {:record => valid_attributes}, valid_session
              }.to change(Record, :count).by(1)
            end
      
            it "assigns a newly created record as @record" do
              post :create, {:record => valid_attributes}, valid_session
              assigns(:record).should be_a(Record)
              assigns(:record).should be_persisted
            end
      
            it "redirects to the created record" do
              post :create, {:record => valid_attributes}, valid_session
              response.should redirect_to(Record.last)
            end
          end
      
          describe "with invalid params" do
            it "assigns a newly created but unsaved record as @record" do
              # Trigger the behavior that occurs when invalid params are submitted
              Record.any_instance.stub(:save).and_return(false)
              post :create, {:record => {}}, valid_session
              assigns(:record).should be_a_new(Record)
            end
      
            it "re-renders the 'new' template" do
              # Trigger the behavior that occurs when invalid params are submitted
              Record.any_instance.stub(:save).and_return(false)
              post :create, {:record => {}}, valid_session
              response.should render_template("new")
            end
          end
        end
      
        describe "PUT update" do
          describe "with valid params" do
            it "updates the requested record" do
              record = Record.create! valid_attributes
              # Assuming there are no other records in the database, this
              # specifies that the Record created on the previous line
              # receives the :update_attributes message with whatever params are
              # submitted in the request.
              Record.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
              put :update, {:id => record.to_param, :record => {'these' => 'params'}}, valid_session
            end
      
            it "assigns the requested record as @record" do
              record = Record.create! valid_attributes
              put :update, {:id => record.to_param, :record => valid_attributes}, valid_session
              assigns(:record).should eq(record)
            end
      
            it "redirects to the record" do
              record = Record.create! valid_attributes
              put :update, {:id => record.to_param, :record => valid_attributes}, valid_session
              response.should redirect_to(record)
            end
          end
      
          describe "with invalid params" do
            it "assigns the record as @record" do
              record = Record.create! valid_attributes
              # Trigger the behavior that occurs when invalid params are submitted
              Record.any_instance.stub(:save).and_return(false)
              put :update, {:id => record.to_param, :record => {}}, valid_session
              assigns(:record).should eq(record)
            end
      
            it "re-renders the 'edit' template" do
              record = Record.create! valid_attributes
              # Trigger the behavior that occurs when invalid params are submitted
              Record.any_instance.stub(:save).and_return(false)
              put :update, {:id => record.to_param, :record => {}}, valid_session
              response.should render_template("edit")
            end
          end
        end
      
        describe "DELETE destroy" do
          it "destroys the requested record" do
            record = Record.create! valid_attributes
            expect {
              delete :destroy, {:id => record.to_param}, valid_session
            }.to change(Record, :count).by(-1)
          end
      
          it "redirects to the records list" do
            record = Record.create! valid_attributes
            delete :destroy, {:id => record.to_param}, valid_session
            response.should redirect_to(records_url)
          end
        end
      
      end
      

      还有一些重要的部分:

      这个位进行编程登录(忽略名字和姓氏属性,它们特定于我正在构建的解决方案):

      before(:each) do
          @user = User.create!(forename: "Billy", surname: "Bob", username: "Test", password: "secret!1", email: "test@test.com")
          login_user
      end
      

      该位保存会话信息/密钥数据:

      def valid_session
          {"warden.user.user.key" => session["warden.user.user.key"]}
      end
      

      正如 diwalak 所写,我们需要将其添加到 spec_help.rb 文件中:

      include Sorcery::TestHelpers::Rails
      

      就是这样 - 无论如何对我有用:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-28
        • 2014-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-08
        • 1970-01-01
        相关资源
        最近更新 更多