测试 测试时 执行多个 before_action 时 顺序颠倒

Awlter1 · January 14, 2018 · Last by Awlter1 replied at January 15, 2018 · 6884 hits
class Admin::VideosController < AdminsController
  before_action :require_user

  def new
  end
end
-----------
class AdminsController < ApplicationController
  before_action :require_admin

  private

  def require_admin
    if !current_user.admin?
      flash[:error] = "You are not allowed to access this page."
      redirect_to home_path
    end
  end
end
------------
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user, :logged_in?

  def current_user
    @current_user ||= User.find_by(id: session[:user_id])
  end

  def logged_in?
    !!current_user
  end

  def require_user
    if !logged_in?
      flash['danger'] = 'You need to sign in'
      redirect_to sign_in_path
    end
  end
end

上面的代码是我创建一个新的控制器AdminsController之后,把Admins::VideoController中的require_admin拿到AdminsController后的结果

请问,在测试的时候 get :new为什么先触发 require_admin这个方法,而不是先触发require_user呢?之前都是按照正常顺序来的。

刚刚在浏览器上在没有登陆的情况下手动输入http://localhost:3000/videos/new, 是先触发的require_user....可是为什么测试时顺序颠倒呢?测试是这样的

describe Admin::VideosController, :type => :controller do
  describe "GET #new" do
    it_behaves_like "requires sign in" do
      let(:action) { get :new }
    end
  end
end
-------
RSpec.shared_examples "requires sign in" do
  it "redirects to sign in path" do
    action
    expect(response).to redirect_to sign_in_path
  end
end

可以悬赏么?一个比特币。。

用 Rails 实地跑了下,会先跑基类的 before_action,再跑子类的 before_action。所以怀疑你后面描述的是否真实。

我也测试了下没发现问题 Rails 5.2 Ruby 2.3.1 Rspec 3.5.4

@davidwei @hw676018683 朋友们 是不是很神奇。。 我用 binding.pry 了,测试的时候的确是先 require_admin 的。。。 ruby (= 2.1.2) rails (= 4.1.1) rspec-rails (= 2.99)

1) Admin::VideosController GET #new behaves like requires sign in redirects to sign in path
    Failure/Error: action
    NoMethodError:
      undefined method `admin?' for nil:NilClass
    Shared Example Group: "requires sign in" called from ./spec/controllers/admin/videos_controller_spec.rb:5
    # ./app/controllers/admins_controller.rb:7:in `require_admin'
    # ./spec/controllers/admin/videos_controller_spec.rb:6:in `block (4 levels) in <top (required)>'
    # ./spec/support/shared_example.rb:3:in `block (2 levels) in <top (required)>'

 2) Admin::VideosController POST #create behaves like requires sign in redirects to sign in path
    Failure/Error: action
    NoMethodError:
      undefined method `admin?' for nil:NilClass
    Shared Example Group: "requires sign in" called from ./spec/controllers/admin/videos_controller_spec.rb:15
    # ./app/controllers/admins_controller.rb:7:in `require_admin'
    # ./spec/controllers/admin/videos_controller_spec.rb:16:in `block (4 levels) in <top (required)>'
    # ./spec/support/shared_example.rb:3:in `block (2 levels) in <top (required)>'
 Finished in 19.17 seconds
 180 examples, 2 failures

真的是睡不着啊,离奇。是什么造成的呢?。。。

正常顺序就是先触发 require_admin 然后 require_user,父类优先。

你在 filter 里面打 log 再访问看看,清除 cookie 再访问看看。

@Rei 额,惊动了您,您说的对,搞定了。

@davidwei 您说的对,确实后面描述地不真实。。

@hw676018683 谢谢,劳烦了。。

比特比为大家存着了🤓 🤓

Awlter1 closed this topic. 15 Jan 01:48
You need to Sign in before reply, if you don't have an account, please Sign up first.