19

rspecリクエストを使用して、各リクエストのヘッダーにapiキーを必要とするJSONAPIをテストしています。

私はこれができることを知っています:

get "/v1/users/janedoe.json", {}, { 'HTTP_AUTHORIZATION'=>"Token token=\"mytoken\"" }

しかし、リクエストごとにそれを行うのは面倒です。

request.envbeforeブロックで設定してみましたが、 no method NilClass errorsinceリクエストが存在しません。

spec-helperこのヘッダーをすべてのリクエストとともにグローバルに送信するには、おそらくで何らかの方法が必要です。

4

4 に答える 4

13

ビフォアフックに設定するには、次のようにアクセスする必要があります

config.before(:each) do
  controller.request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials('mytoken')
end

私も巨大なハッシュが嫌いでしたが、さまざまなステップでユーザーを承認する際に明示的にすることを好みました。結局のところ、それはかなり重要な部分です、そして。だから私の解決策は:

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate user
    token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
    request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
  end
end

#spec/spec_helper.rb
RSpec.configure do |config|
  ...
  config.include ControllerSpecHelpers, :type => :controller

それなら私はそれをそのように使うことができます

describe Api::V1::Users, type: :controller do
  it 'retrieves the user' do
    user = create :user, name: "Jane Doe"
    authorize user
    get '/v1/users/janedoe.json'
  end
end

これは、さまざまな認証レベルをテストするのに最適です。または、ヘルパーメソッドで承認関数を指定して、同じ結果を得ることができます。

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate
    controller.stub(:authenticate! => true)
  end
end

ただし、究極の速度と制御のために、それらを組み合わせることができます

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate user = nil
    if user
      token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
      request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
    else
      controller.stub(:authenticate! => true)
    end
  end
end

次に、ブロック全体を承認します

#spec/spec_helper.rb
...
RSpec.configure do |config|
  ...
  config.before(:each, auth: :skip) { authenticate }

#**/*_spec.rb
describe Api::V1::Users, type: :controller do
  context 'authorized', auth: :skip do
    ...
于 2014-06-08T21:27:41.817 に答える
10

私はこの質問がすでに答えられていることを知っていますが、これが私の見解です。私のために働いた何か:

request.headers['Authorization'] = token

それ以外の:

request.env['Authorization'] = token
于 2017-11-07T11:48:45.260 に答える
6

これは、投稿を行う場合のもう1つの方法です。

@authentication_params = { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(Temp::Application.config.api_key) }

expect { post "/api/interactions", @interaction_params, @authentication_params }.to change(Interaction, :count).by(1)

Interaction_paramsは、私が渡しているjsonオブジェクトにすぎないことに注意してください。

于 2014-02-26T07:28:24.987 に答える
1

ヘッダー自体をテストしていない場合は、ヘッダーに依存する必要はないと思います。HTTP_AUTORIZATIONが存在するかどうかをチェックするメソッドをスタブ化し、その特定のヘッダーをテストする仕様を除くすべての仕様でtrueを返すようにする必要があります。

コントローラー上で...

Controller...
  before_filter :require_http_autorization_token

  methods....

  protected
  def require_http_autorization_token
    something
  end

スペックについて

before(:each) do
  controller.stub!(:require_http_autorization_token => true)
end

describe 'GET user' do
  it 'returns something' do
    #call the action without the auth token
  end

  it 'requires an http_autorization_token' do
    controller.unstub(:require_http_autorization_token)
    #test that the actions require that token
  end
end

そうすれば、トークンを忘れて、本当にテストしたいものをテストできます。

于 2012-10-06T22:59:38.457 に答える