我一直在寻找解决方案很长一段时间,但我无法真正理解实际问题是什么。我正在跟随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
但是,因为测试饼干罐是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分配给cookie变量,即使我使用记住登录,assert session[:user_id].nil?
也会失败(对我而言,这意味着使用cookies
代替{ {1}})。我试图绕过它,但这超出了我的能力。
修改
它越来越怪异了。看起来我多次运行测试后会遇到不同的错误。其中一些只是不时出现。答案 0 :(得分:0)
嗯,这些修改都没有解决我的问题,说实话,我的一些测试开始表现不一致。
我决定翻阅Ruby On Rails Tutorial,发现在集成测试中我没有尝试替换默认的cookie jar,而是在辅助测试中检查cookies
。事实证明,在帮助测试中,cookie jar不是Rack::Test::CookieJar
而是ActionDispatch::Cookies::CookieJar
,这很好并且可以使用signed
方法。对于集成测试,我只依靠修改后的logged_in?
方法,该方法仅测试session[:user_id]
,如下所示:
class ActiveSupport::TestCase
def logged_in?
!session[:user_id].nil?
end
end
为了确保cookies
有效,我为SessionsHelper
创建了一个合适的测试,可以在rails教程中找到。
同样重要的是我低估了session
。我决定在那里存储用户ID,并将其视为用户登录的主要指示符,从而仅使用cookies
来记住用户。通过这种方式,我不必担心在集成测试中测试cookies
,这似乎是错误的。
非常感谢OnlySteveH通过提出一些有用的问题来帮助我。