Devise + CanCan AccessDenied重定向在开发和测试环境之间有所不同

时间:2011-08-11 21:52:34

标签: ruby-on-rails devise integration-testing cancan

我有一个带有Devise和CanCan的Rails 3.1(RC5)应用程序。两者都配置良好并按预期工作,除了当我运行集成测试以确保根据需要重定向AccessDenied时,重定向转到Devise的登录而不是应用程序根。我可以在测试中验证用户是否仍然登录并仍然可以访问应用程序的适用部分。

重定向在此短控制器中定义,其他受限制的控制器继承该控制器(而不是直接继承ApplicationController)。

class AuthorizedController < ApplicationController
  before_filter :authenticate_user!

  rescue_from CanCan::AccessDenied do |exception|
    redirect_to root_url, :alert => exception.message
  end
end

受限制的控制器如下所示:

class Admin::UsersController < AuthorizedController
  load_and_authorize_resource
  def index
    @users = User.all.order('name')
  end
  ...
end

我正在使用默认(ActionDispatch :: IntegrationTest)集成测试;我拥有的唯一额外测试宝石是Capybara,Machinist和Faker(没有RSpec,Cucumber等)。

我的测试看起来像:

def test_user_permissions
  sign_in users(:user)
  get admin_users_path
  assert_response :redirect
  assert_redirected_to root_url
end

测试失败了:

Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/users/sign_in>

当我在开发环境中以限制用户身份登录进行测试时,我按预期重定向到'/',但在集成测试中使用相同类型的用户失败。

在集成测试中,用户实际上并未注销,尽管重定向使其看起来正在发生。当我将测试更改为不测试重定向目标并继续尝试其他URL时,用户仍然登录并且测试通过。

附录&amp;溶液

我最初没有包含持有关键线索的sign_in方法。这是:

module ActionController
  class IntegrationTest
    include Capybara::DSL
    def sign_in (user, password = 'Passw0rd')
      sign_out
      visit root_path
      fill_in 'Email',    :with => user.email
      fill_in 'Password', :with => password
      click_button 'Sign in'
      signed_in? user
    end
    ...
  end
end

我在测试visit和vanilla集成测试访问方法(click_button等)中混合了Capybara访问方法(sign_inget等) 。当我使用Webrat(在Capybara之前)时,这种混合按照我的预期工作,但显然Capybara的会话状态是单独处理的,因此通过Capybara方法的访问被验证,但是通过vanilla集成测试方法访问不是。

1 个答案:

答案 0 :(得分:1)

您没有在ApplicationController中发布您的设计配置,但看起来设计身份/登录检查在CanCan授权检查之前加载(这是有意义的)。

看起来您的测试登录设置无法正常工作,因为当没有有效的用户会话时,'/ users / sign_in'是设计的默认重定向。

由于设计身份检查失败,因此它永远不会进入您的CanCan授权检查。如果还没有用户,为什么要问用户可以做什么。

before_filters将按照它们定义的顺序首先从基础ApplicationController执行,因此子类过滤后的子类过滤器。这就是为什么我认为你的基础ApplicationController中有Devise配置导致它不能命中CanCan。

如果你发布你的Devise配置/代码,我们可能会帮助你进一步调试它。

EDIT / TLDR:

您正在看到重定向登录,因为Devise认为不存在有效的用户会话。您的测试“sign_in()”帮助程序无法按您认为的那样工作。这就是为什么它在开发模式下通过手动登录进行实时用户会话。