如何在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状态代码符号列表。

一方面,响应是通过以下方法构建的:

  • 成功?

  • 重定向?

  • 不能处理的?

  • 完整列表: response.methods.grep(/\?/)

另一方面,Rspec谓词转换每个foo? be_foo匹配器的方法。

不幸的是,不确定你是否能以这种方式获得201,但创建自定义匹配器非常容易。

注意Rails测试仅依赖于一些状态 。

这对我有用:

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

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) 

对于具有适当状态设置的控制器规范,这应该可以正常工作。 它不适用于function规格。 我没有尝试过请求规格,所以你的milage可能会有所不同。

这样做的原因是它利用了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

使用rspec-rails (从rspec 3开始),它可以使用

 expect(response).to have_http_status(:created) 

更新2018-06-11

从Rails 6开始,一些匹配器将被替换(例如successsuccessful )。