【问题标题】:RSpec: Which is the right place for testing authorization?RSpec:哪个是测试授权的正确位置?
【发布时间】:2013-06-19 17:47:46
【问题描述】:

我应该在哪里使用 RSpec 测试授权?

当您使用 RSpec 创建 Rails 应用程序时,似乎有三个文件夹就足够了:

  • 规范/路由
  • 规格/要求
  • 规格/控制器

如果用户登录,我应该在哪一个测试?我应该测试一种以上的规范类型吗?

【问题讨论】:

  • 我会说在控制器和请求中进行测试。路由是为了确保你期望的路由在那里,但这与授权类型测试无关。
  • @ChristopherGillis 谢谢,不要在两个不同的地方测试它会破坏 DRY 原则?

标签: ruby-on-rails ruby testing rspec tdd


【解决方案1】:

您的问题存在细微差别。 Authorization 通常是指用户在应用程序中拥有的权限。 Authentication 推荐用户注册和登录用户。

Authentication 而言,我通常更喜欢使用integration/requests 规格或acceptance/feature specs。最近首选功能规格,因为 Capybara DSL(pagevisit)仅在功能规格中可用。在 2.x 升级之前,它们曾经在请求规范中被允许。

我将测试注册、登录和退出等内容。例如,

# signing_up_spec.rb

feature 'Signing up' do
  scenario 'Successful sign up' do
    visit '/'
    within 'nav' do
      click_link 'Sign up'
    end
    fill_in "Email", :with => "user@ticketee.com"
    fill_in "Password", :with => "password"
    fill_in "Password confirmation", :with => "password"
    click_button "Sign up"
    page.should have_content("Please open the link to activate your account.")
  end
end

这使您可以测试更高级别的方面,并让您看到应用程序中的不同组件(控制器、视图等)协同工作。根据定义,这是一个集成/验收测试。我会为signing_in_spec.rbsigning_out_spec.rb 做同样的事情

现在对于Authorization,我会选择使用控制器规格。这允许您测试用户有权访问的各个操作。这些控制器规范本质上更加细化,并且根据定义是单元/功能测试。例如,假设您有一个票据资源,并且您想测试只有某些用户才能访问某些特定功能

# tickets_controller_spec.rb

describe TicketsController do
  let(:user) { FactoryGirl.create(:confirmed_user) }
  let(:project) { FactoryGirl.create(:project) }
  let(:ticket) { FactoryGirl.create(:ticket, :project => project,
                                  :user => user) }

  context "standard users" do
    it "cannot access a ticket for a project" do
      sign_in(:user, user)
      get :show, :id => ticket.id, :project_id => project.id
      response.should redirect_to(root_path)
      flash[:alert].should eql("The project you were looking for could not be found.")
    end

    context "with permission to view the project" do
      before do
        sign_in(:user, user)
        define_permission!(user, "view", project)
      end

      def cannot_create_tickets!
        response.should redirect_to(project)
        flash[:alert].should eql("You cannot create tickets on this project.")
      end

      def cannot_update_tickets!
        response.should redirect_to(project)
        flash[:alert].should eql("You cannot edit tickets on this project.")
      end

      it "cannot begin to create a ticket" do
        get :new, :project_id => project.id
        cannot_create_tickets!
      end

      it "cannot create a ticket without permission" do
        post :create, :project_id => project.id
        cannot_create_tickets!
      end

      it "cannot edit a ticket without permission" do
        get :edit, { :project_id => project.id, :id => ticket.id }
        cannot_update_tickets!
      end

      it "cannot update a ticket without permission" do
        put :update, { :project_id => project.id,
                       :id => ticket.id,
                       :ticket => {}
                     }
        cannot_update_tickets!
      end

      it "cannot delete a ticket without permission" do
        delete :destroy, { :project_id => project.id, :id => ticket.id }
        response.should redirect_to(project)
        flash[:alert].should eql("You cannot delete tickets from this project.")
      end

      it "can create tickets, but not tag them" do
        Permission.create(:user => user, :thing => project, :action => "create tickets")
        post :create, :ticket => { :title => "New ticket!",
                                   :description => "Brand spankin' new",
                                   :tag_names => "these are tags"
                                 },
                      :project_id => project.id
        Ticket.last.tags.should be_empty
      end
    end
  end
end

我发现rspec-railscapybarafactory_girl_rails 的组合在 Rails 应用程序中的两种类型的测试中都表现良好。

以上示例取自Rails3Book repo on github。查看 repo 以获取更多示例。这是在测试 Rails 应用程序时了解您的可能性的好方法。

【讨论】:

  • 感谢您的回答和参考。就我而言,我正在测试身份验证,因为没有涉及授权系统。所以你基本上主张只在控制器上对未登录的用户进行所有测试,还是我们应该在路由和请求中也进行测试?
  • 由于您没有使用授权(权限),那么您可能可以在功能规范中进行大部分测试。身份验证通常由控制器中的before_filters 组成。因此,只需编写好的综合功能规范,就可以一起测试您的控制器、路由、视图等。这并不意味着你不能测试你的控制器,但在很多情况下它可能会重复。根据经验,我通常为我的每个资源的每个 CRUD 操作编写一个功能规范。我发现这很好用。
猜你喜欢
  • 2010-10-12
  • 1970-01-01
  • 2017-11-03
  • 2020-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-16
相关资源
最近更新 更多