RSpec和受保护的方法,当前用户的控制器规范

13

我可能在错误的方向上前进。我正在使用BDD/TDD先编写规范,但遇到了障碍。

我有这个application_controller_spec.rb文件。

require "spec_helper"

describe ApplicationController do
  describe "current_user" do
    it "should return nil if no one is logged in" do
      subject.current_user.should be_nil
    end
    it "should return currently logged in user" do
      hash = {user_id: "my_id"}
      subject.should_receive(:session).and_return hash
      subject.current_user.should == "my_id"
    end
  end
end

没有使用 protected 关键字也可以完美地运行。

application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_user

  protected
  def current_user
    session[:user_id]
  end
end

启用protected 后,我收到了这个错误消息

NoMethodError: protected method `current_user' called for #<ApplicationController:0x2a90888>

我应该能够使用helper_method进行测试... 有什么建议吗?

2个回答

13

helper_method可以让方法在视图中使用,而不是控制器,参见文档

如果你确实需要从控制器规范(specs)中访问这个方法,你可以使用send

subject.send(:current_user).should be_nil

不过你可能需要考虑测试非公共方法是否有意义,或者是否最好使用视图规范进行测试。或者该方法是否需要首先受到保护。查看 Devise 和 Authlogic 如何实现对其 current_user 方法进行测试也可能很有帮助。


这是一个特殊情况,它是公共API的一部分,通过helper_method实现,因此应该在隔离环境中进行规格说明,但由于其被标记为受保护(似乎对于current_user是一个成熟的模式),这使得编写规格说明变得更加困难......我将研究devise源代码。谢谢! - oma
1
Devise 生成 current_user,作为 def current_#{mapping} 存在于 lib/devise/controllers/helper.rb#self.define_helpers 中。没有独立的测试,只有通过 helpers 和 assigns(:current_user) 进行测试。这样的通用代码难以浏览。我希望能够访问 helper_method,因为它是公共 API 的一部分。 - oma
为了澄清一些问题 - send 在这里需要的原因与 helper_method 无关,仅仅是因为该方法受保护。 - Josh Dzielak

3

虽然原问题已经过去了一段时间,但也许有人会发现这个方法很有用。

你可以创建ApplicationController的匿名子类,并在其中公开受保护的方法。不需要使用send()方法。

以下是具体步骤:

describe ApplicationController, type: :controller do
  controller do
    def current_user
      super
    end
  end

  ...

  it 'should return nil if no one is logged in' do
    expect(controller.current_user).to be_nil # (or whatever)
  end

end

这篇 SO 回答的来源是 这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接