【发布时间】:2019-02-03 03:40:10
【问题描述】:
我有一个多租户应用程序,它将 Apartment 用于 postgreSQL 模式,将 Devise 用于用户身份验证。在我尝试编写一些集成测试之前,一切都运行顺利。
这是我目前所拥有的精简版(请随时询问更多信息):
# test/support/sign_in_helper.rb
module SignInHelper
def sign_in_as(name)
sign_in users(name)
end
end
# test/test_helper.rb
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
#...
class ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
include SignInHelper
end
# test/system/article/post_test.rb
require "application_system_test_case"
class Article::PostTest < ApplicationSystemTestCase
test 'post a new document' do
sign_in_as :will
visit articles_path
click_on 'Add New Article' # redirected to login page after clicking this button
fill_in 'Name', with: 'Hello world!'
fill_in 'Content', with: 'Yes yes'
click_on 'Create Article'
assert_select 'h1', /Hello world!/
end
end
articles_path 需要经过身份验证的用户,所以我知道登录助手有效。然而,每当我尝试转到另一个链接时,突然用户就无法通过身份验证。
我像这样修改了 Devise 的 authenticate_user! 方法:
def authenticate_user!(*args)
byebug
super
end
并确认warden.authenticated? 为articles_path 返回了true 但false 随后尝试导航到new_article_path。
我在集成测试类型、控制器和系统中都注意到了这种行为。但是,在开发环境中使用此应用时,这不是问题。
最令人沮丧的部分是,我有一个不同的应用程序,它的设置似乎与此应用程序相同,但在测试时不会出现此身份验证问题。
我该如何调试这个问题?
系统
- 导轨:5.2.2
- 设计:4.5.0
- 水豚:3.13.2
更新 1(2019 年 2 月 4 日)
这是 @BKSpureon 要求的 Articles 控制器
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :archive]
def index
@articles = Article.where(archived: false)
end
def show
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article, notice: 'Your article was successfully created.'
else
flash[:error] = @article.errors.full_messages.to_sentence
render :new
end
end
def edit
end
def update
if @article.update(article_params)
redirect_to articles_path, notice: 'Your article was successfully updated.'
else
flash[:error] = @article.errors.full_messages.to_sentence
render :edit
end
end
def archive
if @article.archive!
redirect_to articles_path, notice: 'Your article was successfully archived.'
else
render :edit
end
end
private
def set_article
@article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:name, :content, :archived)
end
end
更新 2(2019 年 2 月 4 日)
我写了简单的中间件,放在Warden之前调试:
# lib/debug_warden_middleware.rb
class DebugWardenMiddleware
def initialize(app)
@app = app
end
def call(env)
@status, @headers, @response = @app.call(env)
if env['warden'].present?
puts "User (#{env['warden'].user.present?}), Class: #{@response.class.name}"
end
return [@status, @headers, @response]
end
end
# config/application.rb
#...
module AppName
class Application < Rails::Application
# ...
config.middleware.insert_before Warden::Manager, DebugWardenMiddleware
end
end
而且我注意到,warden 似乎在每次请求后都会清除其用户,包括资产请求:
bin/rails test:system
Run options: --seed 39763
# Running:
Capybara starting Puma...
* Version 3.9.1 , codename: Private Caller
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:57466
User (true), Uri: ActionDispatch::Response::RackBody
User (false), Uri: Sprockets::Asset
User (false), Uri: Sprockets::Asset
User (false), Uri: Sprockets::Asset
User (false), Uri: ActionDispatch::Response::RackBody
User (false), Uri: ActionDispatch::Response::RackBody
User (false), Uri: Sprockets::Asset
[Screenshot]: tmp/screenshots/failures_test_post_a_new_article.png
E
Error:
Agenda::PostTest#test_post_a_new_article:
Capybara::ElementNotFound: Unable to find field "Name"
test/system/article/post_test.rb:9:in `block in <class:PostTest>'
bin/rails test test/system/article/post_test.rb:4
附带说明一下,我同时使用 Sprockets 和 Webpacker。
【问题讨论】:
-
粘贴到文章控制器中。一些想法:(i)在
articles_path视图中添加<% byebug %>,然后查看您那里是否有当前用户 - 以及该用户是否已登录? (ii) 再次使用byebug检查文章控制器中的new操作是否已被击中,并再次检查那里是否有current_user。然后逐行检查您是否还有当前用户。希望对您有所帮助。 -
谢谢@BKSpureon,我已经用 ArticlesController 更新了这个问题。将
<% byebug %>插入索引视图时,我发现用户已 登录。但是它永远不会进入new操作,因为它失败了Devise 的before_actionauthenticate_user!。这就是为什么我认为它与未在测试环境中持续存在的会话有关。 -
试试去掉monkey补丁,在你的登录助手中,添加一个bybug语句,测试用户是否成功登录?
-
我不确定如果用户在没有猴子补丁的情况下登录,我将如何测试。在集成测试中,我无权访问
current_user、warden或env。 -
我的猜测是您的设置有问题,导致通过登录设置的身份验证 cookie 在以后的请求中无法发送(或接受)。如果没有工作示例,很难调试。看一下 Benj 为 this question 创建的 github.com/randoum/as_bug 作为示例/起点,用于创建一个最小的示例来调试 RSpec on Rails 问题,并创建类似的东西供我们深入研究。
标签: ruby-on-rails devise integration-testing minitest warden