【发布时间】:2017-11-29 06:41:46
【问题描述】:
我一直在寻找解决方案很长时间,但我无法真正理解实际问题是什么。我正在关注 Michael Hartl 的 Ruby On Rails 教程,并尝试为登录进行一些集成测试。经过一些修改后,测试文件中的代码如下所示:
test 'login without remembering' do
login_as @user, remember: '1'
delete logout_path
login_as @user, remember: '0'
assert_not session[:user_id].nil?
assert_nil cookies[:remember_token]
assert_nil cookies[:user_id]
end
test 'login with remembering' do
login_as @user, remember: '1'
assert logged_in?
assert_not_empty cookies[:remember_token]
assert_not_empty cookies[:user_id]
assert session[:user_id].nil?
assert_equal assigns(:user).remember_token, cookies[:remember_token]
end
logged_in? 方法可通过include SessionsHelper 在ActionDispatch::IntegrationTest 中使用。它的核心部分是找到一个用户:
if (user_id = session[:user_id]) # User is not remembered
@current_user = User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id]) # User is remembered
user = User.find_by(id: user_id)
remember_token = cookies[:remember_token]
(@current_user = user) if user && user.authenticated?(remember_token)
end
但是,因为测试 cookie jar 是 Rack::Test::CookieJar 这根本不起作用并引发 NoMethodError: undefined method 'signed' for #<Rack::Test::CookieJar:0x00000006796390>
This 很有用,帮助我解决了问题。经过一段时间的思考,我做到了:
class ActionDispatch::IntegrationTest
# Get ActionDispatch::Cookies::CookieJar because Rack::Test::CookieJar
# doesn't support signed cookies
def cookies
cookies = ActionDispatch::Request.new(Rails.application.env_config).cookie_jar
end
include SessionsHelper
def login_as(user, password: 'Password', remember: '0')
post login_path, params: { session: { email: user.email,
password: password,
remember: remember } }
# Set cookies manually
return if remember == '0'
user = assigns(:user)
return if user.remember_token.nil?
cookies[:remember_token] = user.remember_token
cookies.signed[:user_id] = user.id
end
end
但是,我仍然不明白为什么它可以解决我的问题以及它是否是一个好的解决方案。如果我没有在cookies 方法中将请求对象中的cookie_jar 分配给cookies 变量,即使我使用记住登录(对我来说这意味着使用cookies 而不是session),assert session[:user_id].nil? 也会失败。我正在努力解决这个问题,但这超出了我的能力范围。
编辑:
它变得越来越奇怪了。多次运行测试后,我似乎遇到了不同的错误。其中一些只是不时出现。
【问题讨论】:
-
我无法检查您的代码,因为您添加了书中没有的行。我可以提供帮助的是一个 Bitbucket 存储库,其中包含整个教程的完整代码。我添加了更多测试,因此我的部分回购与本书不完全一致。你看到了什么错误;哪些测试失败了?如果你有一个回购,我可以把它拉下来并在这里复制错误,也许。
-
@OnlySteveH,对不起,我实际上重新实现了登录系统,以便它可以记住多个浏览器上的用户。这是带有我发布的代码的仓库:github.com/CosmicKid/LucidTracker/tree/account-activation 它有时会说缺少模板(但这与我现在要解决的问题并不真正相关),它还表明用户已登录(users_signup_test.rb :29)即使它没有被激活(但它可能是由于手动设置 cookie 而没有检查它是否被激活)。它也会在我提到的
assert session[:user_id].nil?上中断。 -
不过,我基本上需要的是测试用户是否登录。唯一让它变得困难的是我无法真正测试
cookies,因为Rack::Test::CookieJar没有签名方法。 -
我已经把它拉到了 c9 中。测试在第一次运行时失败,
assert session[:user_id].nil?行。我认为这是正确的——即使remember设置为'0',会话也会有一个ID。但是,再次运行测试时,它们都是绿色的。我只在第一次运行时失败了。 -
这里,“几乎”意味着我可能低估了
session的力量。昨天我修复了注销错误,该错误是由每次用户注销时重置会话引起的——事实证明,它不仅删除了用户的 id,而且还删除了与除GET之外的所有 html 请求一起传递的特殊令牌。如果它如此重要,我可能应该将其作为用户 id 的存储并使用cookies仅用于记住用户 - 所以与教程中的方法相同。我会在决定更改登录系统之前尝试一下。
标签: ruby-on-rails cookies