0

rspec 統合 (リクエスト) テストで API をテストしようとしています。

ブラウザで API エンドポイントにアクセスすると0.0.0.0:3000/api/regions、データが返され、セッション ID が取得され、すべてが機能しているように見えます。

API でラック保護を使用しています。

module Api
  class Root < Grape::API
     use Rack::Protection, instrumenter: ActiveSupport::Notifications
     use Rack::Protection::AuthenticityToken    
     prefix  'api'

     helpers do
        def warden
          request.env['warden']
        end
     end

     version 'v1', using: :header, vendor: 'vendor', strict: false do
        mount Resources::V1::Search => '/'
        mount Resources::V1::Regions => '/'
     end    

   end
end

API リソース:

module Resources
  module V1
    class Regions < Grape::API

      resource :regions do
        get do
          # Some code...
        end
      end
    end
  end
end

spec_helper.rb

[...]
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods

  config.include Rack::Test::Methods, type: :request
  config.include Module.new { def app; Api::Root; end }, type: :request

  config.include Warden::Test::Helpers

  # ## Mock Framework
  #
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
  #
  # config.mock_with :mocha
  # config.mock_with :flexmock
  # config.mock_with :rr

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # If true, the base class of anonymous controllers will be inferred
  # automatically. This will be the default behavior in future versions of
  # rspec-rails.
  config.infer_base_class_for_anonymous_controllers = false

  # Run specs in random order to surface order dependencies. If you find an
  # order dependency and want to debug it, you can fix the order by providing
  # the seed, which is printed after each run.
  #     --seed 1234
  config.order = "random"
end

ここにテストがあります:

describe Resources::V1::Regions do
  describe 'GET /regions' do
    it 'returns some data' do
      get '/api/regions'
      [... expectations - doesn't get here...]
    end
  end
end

エラーは次のとおりです。

 RuntimeError:
       you need to set up a session middleware *before* Rack::Protection::RemoteToken
     # ./spec/requests/api/region_spec.rb:6:in `block (3 levels) in <top (required)>'

ここから来ます: https://github.com/rkh/rack-protection/blob/master/lib/rack/protection/base.rb#L85

では、ラック セッション ミドルウェアを追加する必要がありますね。

use Rack::Session::Cookie, secret: '...'request.env['warden'] がnilになるようにするAPIに追加します(別の質問は別の時間です)。

ただし、ブラウザでエンドポイントをロードすると、次のようになります。

undefined method `each' for #<ActionDispatch::Request::Session:0x7f7bf9e521e0 not yet loaded>

ここで発生します: https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb#L158

use Rack::Session::Cookieサーバーによってロードされたときに他の何かがそれを行っているため、必要はないと思いますが、テストが機能するために何かを追加する必要があります。それが何であるかわかりません。

他に情報が必要な場合はお知らせください。

バージョン:

  • ブドウ (0.6.1)
  • レール (4.0.2)
  • ラック保護 (1.5.2)
  • rspec (2.14.1)
4

1 に答える 1

0

リクエストの 3 番目の引数に「rack.session」ハッシュを追加することで、これを解決していました。get '/api/regions', {}, {'rack.session' => {}}

しかし、より良い方法を見つけました: https://github.com/heavysixer/grape-on-rack/pull/1 は、セッションを追加し、同時にワーデンの問題を解決します。

RSpec.configure do |config|
[...]
  rack_app = Module.new do 
    def app
      @app ||= Rack::Builder.new do
        use Rack::Session::Cookie
        Warden::Manager.serialize_into_session { |user| user.id }
        Warden::Manager.serialize_from_session { |id| User.get(id) }
        use Warden::Manager do |manager|
          manager.default_strategies :password, :basic
          # manager.failure_app = Acme::BadAuthentication
        end
        run Api::Root
      end
    end
  end

  config.include rack_app, type: :request
  end

誰かがより良いものを持っていない限り、回答としてマークします。

于 2014-03-16T17:56:45.553 に答える