为未登录的用户测试重定向时,"uncaught throw:warden"

ell*_*lmo 8 rspec ruby-on-rails devise warden

这是一个非常典型的控制器的规范,before_filter当未登录的用户(也称为访客)尝试访问时,该控制器会重定向到登录页面/projects/new.

describe ProjectsController do
  (...)

  describe "GET new" do
    context 'when not logged in' do
      before { sign_in_nobody }

      context 'creating project' do
        before { get :new }

        it 'denies access' do
          expect(response).to be_redirect
        end
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我已经specced访问的所有可能的结果:index,:show并:new为来宾,用户,管理员和superadmins.我没有使用任何记录或访客用户,管理员或没有任何问题 - 但这实际上是这个规范第一次涉及涉及Devise的行动,before_filter :autheticate_user!并且它在此失败了.

正如你可能已经怀疑的那样 - 规格甚至没有达到expect(response).to be_redirect,它在之前引发了一个混合:

Failures:

1) ProjectsController GET new when not logged in creating project denies access
   Failure/Error: get :new
   ArgumentError:
     uncaught throw :warden
   # ./spec/controllers/projects_controller_spec.rb:344:in `block (5 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

我已经搜索了一个问题的答案:"如何使用rspec和设计正确测试未经身份验证的(访客)用户",但是每个人只讨论在设计中为RSpec实际记录用户时遇到问题.我解决的问题是:

#spec/support/devise_authenticators.rb
include Devise::TestHelpers

def sign_in_nobody
  @request.env["devise.mapping"] = Devise.mappings[:user]
  sign_in User.new
end

def sign_in_user
  @request.env["devise.mapping"] = Devise.mappings[:user]
  sign_in FactoryGirl.create(:user)
end
Run Code Online (Sandbox Code Playgroud)

然而,这不是登录失败,这是"没有记录".到目前为止,我绝对没有和我认识的人HAVE以某种方式测试这些场景.

现在我正在使用一个解决方法:

before { sign_in_nobody }

context 'creating project' do
  it 'denies access' do
    expect{ get :new }.to raise_exception("uncaught throw :warden")
  end
end
Run Code Online (Sandbox Code Playgroud)

但即使它实际上是正确的(uncaught throw :warden仅在authenticate_user!失败时发生,因此可以用作期望)理论上它感觉非常脏.

任何想法如何正确地做到这一点?

(...也许我根本不应该测试这个,看看before_filter authenticate_user!Devise的责任不是我的责任的正确性?)

Sam*_*rbi 4

它应该可以工作。我刚刚花了一段时间修复同样的问题,结果发现我们有一个测试助手可以覆盖process控制器测试。Devise 还重写了它,catch :warden所以我只需要include Devise::TestHelpers在包含默认参数模块之前就可以。

有关当我说我们覆盖时我所说的示例process,请参阅此答案,它描述了如何设置要包含的默认参数format: json