RSpec如何正确构建测试?

时间:2015-03-10 11:28:59

标签: ruby-on-rails ruby-on-rails-3 unit-testing ruby-on-rails-4 rspec

我正在使用具有REST API的Rails编写应用程序。除非用户已获得授权,否则大多数控制器都无法访问。通过插入检查用户在控制器中的before_action挂钩中的权限的方法来完成它。我想测试未经授权的用户无法访问API的某些部分。目前我这样做:

要求' rails_helper'

RSpec.describe RoomsController, type: :controller do
  ...
  describe "while unauthenticated" do
    before do
      logout
    end

    def expect_unauth
      expect(response).to have_http_status(:unauthorized)
    end

    it "GET #index returns http unauthorized" do get :index; expect_unauth end
    it "GET #show returns http unauthorized" do get :show, {id: 1}; expect_unauth end
    it "DELETE #destroy returns http unauthorized" do delete :destroy, {id: 1}; expect_unauth end
    it "POST #create returns http unauthorized" do post :create, {id: 1}; expect_unauth end
    it "PUT #update returns http unauthorized" do put :update, {id: 1}; expect_unauth end
  end

它可以工作,但对于每个控制器来说几乎都是一样的。如何在不在每个控制器中复制粘贴此代码的情况下进行此类测试?我是否应该测试它,或者因为它非常简单我应该假设它可以工作并为特定的控制器功能编写测试?

此外,它甚至属于控制器规格吗?也许它应该是一个请求规范?

2 个答案:

答案 0 :(得分:1)

我通常将此代码用于相同的行为:

ACTIONS = [
  [ :index, :get, {} ],
  [ :show, :get, { :id => 1 }],
  [ :delete, :destroy, { :id => 1 }]
]

ACTIONS.each do |action, method, params|
  it "shout return unauthorized when #{method} #{action}" do
    send(method, action, params)
    expect_unauth
  end
end

答案 1 :(得分:1)

为什么需要在每个控制器操作上测试expect_unauth?

我假设您在ApplicationController中进行了auth检查,或者在所有控制器通用的地方进行了验证。即,所有需要认证的API动作在未经授权的访问时以相同的方式响应。因此,在每一个动作上测试它都是多余的。您可以编写一个规范来测试未经授权的系统访问是否按预期响应。

在测试操作功能的示例中,系统首先检查以确保存在有效登录,如果没有,则测试中的下一个期望将失败。

要回答您是否应该使用控制器规格或请求规格的问题,请查看rspec_api_documentation。它将请求规范与文档生成器结合在一起。

如果这对你来说太过分了,那么我认为对于API测试来说,它是控制器规范和请求规范之间的界限。控制器规范存根视图,所以如果你想检查实际响应中的某些内容,例如JSON中有特定内容,那么你可以使用请求规范。