我正在尝试测试我的控制器并保持关注点分离。
第一个问题是“谁能够执行哪个行动?”
我使用 authlogic 进行身份验证,使用 be9's acl9 进行授权。但这并不重要,我的所有授权问题都在before_filter
处理。我正在通过与此类似的东西测试这样的before_filter
:
describe SomeModelsController, "GET to index (authorization)" do
before(:each) do
@siteadmin = mock_model(User)
@siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true)
end
it "should grant access to a siteadmin" do
controller.should_receive(:current_user).at_least(:once).and_return(@siteadmin)
get :index
response.should be_success
end
end
此规范工作正常!
现在,第二个问题是“行动是否按预期进行?”
这不涉及检查授权。最好/最干净的解决方案是将before_filter
全部一起跳过,然后执行以下操作:
describe SomeModelsController, "GET to index (functional)" do
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
无需担心哪个角色的用户必须先登录。现在我解决了这个问题:
describe SomeModelsController, "GET to index (functional)" do
before(:each) do
@siteadmin = mock_model(User)
@siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true)
controller.stub!(:current_user).and_return(@siteadmin)
end
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
如果我现在决定我的siteadmin无权再访问索引操作,那么它不仅会破坏一个规范 - 即在这种情况下必须破坏的规范 - 而且还有完全不相关的第二个规范。
我知道这基本上是一个小问题,但如果有人想出一个(优雅的)解决方案会很好!
答案 0 :(得分:34)
要跳过前过滤器:
controller.class.skip_before_filter :name_of_method_used_as_before_filter
一个警告(mentioned the docs)是这只适用于方法参考过滤器,而不是过程。
或者,您可以存根current_user.has_role?
describe SomeModelsController, "GET to index (functional)" do
before(:each) do
controller.current_user.stub!(:has_role?).and_return(true)
end
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
答案 1 :(得分:0)
老问题,但最近我不得不解决这个问题。这仅适用于Rails 3.1,对于早期版本,您应将_process_action_callbacks
替换为filter_chain
(未经测试)
您可以简单地从过滤器链中删除匹配的Proc,如下所示(Test :: Unit example):
class RandomControllerTest < ActionController::TestCase
def setup
@controller.class._process_action_callbacks.each do |f|
@controller.class._process_action_callbacks.delete(f) if f.raw_filter.to_s.match(/**<match for your proc>**/)
end
end
end
答案 2 :(得分:-9)
如何不做GET请求? 尝试单独调用控制器方法。
controller.index