У меня есть приложение Rails 3.1 (RC5) с Devise и CanCan. Оба настроены хорошо и работают как положено, за исключением того, что когда я запускаю интеграционные тесты, чтобы убедиться, что 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); Единственные дополнительные драгоценности для тестирования, которые у меня есть, это Капибара, Машинист и Фейкер (без 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-адреса, пользователь все еще вошел в систему и тест прошел.
Приложение и решение:
Изначально я не включал метод 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
Я смешивал в тесте методы доступа Capybara (visit
, click_button
и т. Д.) В sign_in
и методы доступа к тесту интеграции ванили (get
и т. Д.). Когда я использовал Webrat (до Capybara), это микширование работало так, как я ожидал, но, очевидно, состояние сеанса Capybara обрабатывается отдельно, поэтому доступ через методы Capybara был аутентифицирован, а доступ через методы тестирования ванильной интеграции не был.