17

我正在尝试测试我的控制器并保持关注点分离。

第一个问题是“谁能够执行哪个动作?”
我使用authlogic进行身份验证,使用be9 的 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

如果我现在决定我的站点管理员不再有权访问索引操作,它不仅会破坏一个规范 - 即在这种情况下必须破坏的规范 - 而且还会破坏完全不相关的第二个规范。

我知道这基本上是一个小问题,但如果有人能想出一个(优雅的)解决方案,那就太好了!

4

3 回答 3

34

要跳过之前的过滤器:

controller.class.skip_before_filter :name_of_method_used_as_before_filter

一个警告(提到文档)是这仅适用于方法引用过滤器,而不适用于过程。

或者,您可以存根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
于 2009-11-20T18:08:27.573 回答
0

老问题,但我最近才不得不解决这个问题。这仅适用于 Rails 3.1,对于早期版本,您应该替换_process_action_callbacksfilter_chain(untested)

您可以像这样简单地从过滤器链中删除匹配的 Proc(Test::Unit 示例):

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
于 2011-11-27T16:55:13.417 回答
-9

不做 GET 请求怎么样?尝试自己调用控制器方法。

controller.index
于 2009-11-24T06:28:14.197 回答