Ruby on Rails Pundit的current_user在集成测试中是零

Jak*_*ith 7 integration-testing devise ruby-on-rails-4 pundit

我正在使用宝石punditdevise.我有一个删除链接,只有在你是管理员时才显示.我有一个集成测试,我想验证删除链接只显示给管理员.

test 'comment delete link shows when it should' do
  log_in_as @admin
  get movie_path(@movie)
  assert_select 'a[href=?]', movie_comment_path(comments(:one), @movie.id)
end
Run Code Online (Sandbox Code Playgroud)

test_helper.rb看起来像这样:

...
class ActiveSupport::TestCase
  ...
  def log_in_as(user, options = {})
    password = options[:password] || 'password'
    if integration_test?
      post user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
    else
      Devise::TestHelpers.sign_in user
    end
  end

  private

    # Returns true inside an integration test.
    def integration_test?
      defined?(post_via_redirect)
    end

end
Run Code Online (Sandbox Code Playgroud)

response.body看上去一切正常,但确确实实没有删除链接.当我运行开发服务器并自己访问该页面时,有一个.我已经把这个缩小到current_user政策中的权威人士使用的值为nil.这是我的comment_policy.rb:

class CommentPolicy
  attr_reader :current_user, :comment

  def initialize(current_user, model)
    @current_user = current_user
    @comment      = model
  end

  def create?
    if @current_user
      @current_user.member? or @current_user.content_creator? or @current_user.moderator? or @current_user.admin?
    end
  end

  def destroy?
    if @current_user
      @current_user == @comment.user or @current_user.moderator? or @current_user.admin?
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

作为结束语,我听说Rails 5选择了集成测试而不是控制器测试,因为我们从Rails 4中知道它们是为我们的控制器生成的默认测试类型.如果是这种情况,devise那么当使用Rails 5时,如果在控制器测试中工作的sign_in/ sign_outhelper也可以在集成测试中工作,那么开箱即用将会非常有用.但我还有这个pundit不知道current_user是什么的问题吗?我假设这一切在控制器测试中都能正常工作,因为current_user它的作用域是控制器吗?关于这个主题的任何和所有的亮点都非常感谢,但我真的想弄清楚如何让集成测试与这个设置一起工作,因为我现在有大约10亿我想写.

Bil*_*son 2

这并不是说它完全重要,而是它是否需要在策略中使用 current_user 或者可以只在策略中使用 user 。我的意思是,根据 Github 上的 elabs/pundit 自述文件,我只会在任何地方使用@useranduser而不是current_user. 如果我让你感到困惑,请阅读自述文件。

此外,当您的请求没有有效的 CSRF 令牌时,通常会发生nilfor 。current_user当您通过转到 或 w/e 在网站上手动执行此操作时,您首先在登录路径上localhost:3000执行 a,然后再使用您的凭据在登录路径上执行发布操作。get在您的集成测试中,我似乎没有看到您在哪里执行此操作get以获得会话的 CSRF。

希望这可以帮助!!!