如何测试before_filter在Rails中正确使用RSpec
我的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之后是否调用了特定的操作? 我正在寻找像controller.should_receive(:action_name)
(它不起作用)来替换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_else
或render :text => "foobar"
,此时我们并不关心。
在排序中,我现在需要的是找到一种方法使RSpec 不担心模板的存在。
当存根时,你仍然可以给出一个虚拟实现。 在该实现中,您可以引发错误,确保所有执行都停止,或者您仍然执行重定向。
例如
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文档 。
希望能帮助到你。
扩展@ nathanvda的答案 :
当存根时,你仍然可以给出一个虚拟实现。 在该实现中,无论如何都要进行重定向。
您需要在块中指定controller
:
expect(controller).to receive(:redirect_to_log) { controller.redirect_to login_url }
RSpec有一个匹配器,也称为redirect_to
,在查找方法时优先。 直接在控制器上调用它可以解决这个问题。
最后的解决方案,感谢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