如何测试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_elserender :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