web-dev-qa-db-ja.com

RSpecでHTTPステータスコードシンボルを使用する方法

次のようなコントローラのコードで HTTPステータスコードシンボル を使用します。

render json: {
    auth_token: user.authentication_token, 
    user: user
  }, 
  status: :created

または

render json: {
    errors: ["Missing parameter."]
  }, 
  success: false, 
  status: :unprocessable_entity

私のリクエスト仕様のコードでは、シンボルも使用したいと思います:

post user_session_path, email: @user.email, password: @user.password
expect(last_response.status).to eq(201)

...

expect(last_response.status).to eq(422)

ただし、整数の代わりに記号を使用する各テストは失敗します。

Failure/Error: expect(last_response.status).to eq(:created)

  expected: :created
       got: 201

  (compared using ==)

RackのHTTPステータスコードシンボル の最新のリストを次に示します。

29
JJD

一方、応答は次のようなメソッドで構築されます。

  • 成功?

  • リダイレクト?

  • 処理できませんか?

  • 完全なリストは:response.methods.grep(/\?/)

一方、Rspec述語は、すべてのfoo?メソッドをbe_fooマッチャーに変換します。

残念ながらこの方法で201を使用できるかどうかはわかりませんが、カスタムマッチャーの作成は非常に簡単です。

注Railsテストのみ いくつかのステータスに依存

11
apneadiving

responseオブジェクトは、いくつかのシンボルタイプにメッセージとして応答します。だからあなたは単に行うことができます:

expect(response).to be_success
expect(response).to be_error
expect(response).to be_missing
expect(response).to be_redirect

:createdなどの他のタイプの場合、これをラップする単純なカスタムマッチャーを作成できます assert_response

RSpec::Matchers.define :have_status do |type, message = nil|
  match do |_response|
    assert_response type, message
  end
end

expect(response).to have_status(:created)
expect(response).to have_status(404)

これは、適切な状態が設定されているコントローラー仕様では正常に機能するはずです。機能仕様では機能しません。私はリクエストスペックで試したことがないので、あなたの距離はそこで異なるかもしれません。

これが機能する理由は、RSpecコントローラーの仕様に裏で同様の状態設定があるという事実を利用しているためです。したがって、assert_response@responseにアクセスすると、それが使用可能になります。

このマッチャーは、おそらくassert_responseが使用するコードをマッチャーに単にコピーすることで改善できます。

RSpec::Matchers.define :have_status do |type, message = nil|
  match do |response|
    if Symbol === type
      if [:success, :missing, :redirect, :error].include?(type)
        response.send("#{type}?")
      else
        code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
        response.response_code == code
      end
    else
      response.response_code == type
    end
  end

  failure_message do |response|
    message or
      "Expected response to be a <#{type}>, but was <#{response.response_code}>"
  end
end

更新:2014-07-02

これは、RSpec Rails 3 :: https://www.relishapp.com/rspec/rspec-Rails/v/3-0/docs/ matchers/have-http-status-matcher

21
Aaron K

これは私にとってはうまくいきます:

expect(response.response_code).to eq(Rack::Utils::SYMBOL_TO_STATUS_CODE[:not_found])
21
cyrilchampier

rspec-Railsrspec3以降)を使用して、

expect(response).to have_http_status(:created)

2018年6月11日更新

Rails 6以降、一部のマッチャーが置き換えられます(例:success by successful)。

9
schmijos