【问题标题】:How to test that a before_filter works correctly with RSpec in Rails如何测试 before_filter 与 Rails 中的 RSpec 一起正常工作
【发布时间】:2011-08-18 09:30:49
【问题描述】:

我的 ApplicationController 中有一个 check_user_access_control before_filter,它在允许登录用户通过之前检查登录用户的角色和权限。我正在尝试对其进行一些测试,但我找不到这样做的好方法。

对于简单的索引操作,我只是这样做:

it "allows access to mod" do
  login_as(Factory(:mod)) # this is a spec helper
  get :index
  response.code.should == "200"
end

它工作得很好。对于需要一些参数的编辑/显示/创建和其他操作、与数据库的交互以及运行后可能的重定向,它需要存根太多其他东西。

有没有办法测试是否在 before_filters 之后调用了特定操作?我正在寻找类似 @​​987654323@ 的东西(不起作用)来替换 response.code.should == "200" 行与。

版本:rails 3.0.4 和 rspec 2.5

我尝试了另一种方法。我们在 ApplicationController 中有一个名为 redirect_to_login 的方法,我现在正在使用 controller.should_receive(:redirect_to_login) 检查它并且可以正常工作。

虽然它正确检测用户是否被允许,但它会存根方法,这意味着无论用户是否被允许,控制器操作都会运行。此外,该操作取决于参数和数据库,我们不希望这样。

如果现在我使用controller.stub!(:action_name) 存根操作方法,则操作不会运行,但 RSpec 仍在寻找模板。好吧,有些动作没有模板,它们只是以 redirect_to :action => :somewhere_elserender :text => "foobar" 结尾,此时我们并不关心。

总的来说,我现在需要的是找到一种方法让 RSpec 担心模板的存在。

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    当存根时,您仍然可以提供一个虚拟实现。在该实现中,您可以随后引发错误,以确保所有执行都停止,或者您仍然进行重定向。

    例如

    controller.should_receive(:redirect_to_log) { redirect_to login_url }
    

    controller.should_receive(:redirect_to_log) { raise StandardError.new('login error') }
    expect { get :index }.to raise_error
    

    有关更多信息,请查看很棒的rspec documentation

    希望对你有帮助。

    【讨论】:

    • 第一个块似乎不起作用,但第二个块(引发错误的块)就像一个魅力!现在,开始寻找一种相反的方法:当我们在示例中有controller.should_not_receive(:redirect_to_log) 时,阻止操作方法运行。
    • 通常我肯定会测试您作为before_filter 独立使用的方法:给定一个用户,它是否会做出正确的决定是否允许访问。在您的控制器上,您可以测试:如果不应允许用户访问,则应调用 redirect_to_log(如上所示)。如果用户有权访问,则不应调用 redirect_to_logresponse.status.should == 200(在这种情况下,我假设您在查找视图时不会遇到麻烦,对吧?)。所以只需测试它是否成功。
    • 我尝试了这种方法,但问题是某些操作(如创建)不是以 200 结尾而是以 302 结尾(重定向到显示)。他们中的一些人还需要大量的参数和数据库访问功能(甚至是其中一些的文件系统访问权限),我想绕过因为你只能存根这么多。 运行操作方法本身就是要我死的原因,因为它不是这些授权测试的目的。
    • 我想找到方法了!!!一旦我确信它可以正常工作,就会将其作为问题的编辑发布。
    【解决方案2】:

    扩展@nathanvda's answer

    当存根时,您仍然可以提供一个虚拟实现。在该实现中 [...] 无论如何都要进行重定向。

    您需要在块中指定controller

    expect(controller).to receive(:redirect_to_log) { controller.redirect_to login_url }
    

    RSpec 有一个匹配器,也称为redirect_to,它在查找方法时具有优先权。直接在控制器上调用它可以解决这个问题。

    【讨论】:

      【解决方案3】:

      最终解决方案,感谢 nathanvda:

      it "allows access to moderator" do
        login_as(Factory(:mod))
        controller.stub!(action) { raise "HELL" }
      
        controller.should_not_receive(:redirect_to_login)
        expect { get action }.to raise_error(/HELL/)
      end
      
      it "denies access to user" do
        login_as(Factory(:user))
      
        controller.should_receive(:redirect_to_login) { raise "HELL" }
        expect { get :index }.to raise_error(/HELL/)
      end
      

      发布于https://gist.github.com/957565

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        • 1970-01-01
        • 2012-08-08
        • 2012-01-23
        相关资源
        最近更新 更多