我正在尝试通过向我的 SessionsController
发出 POST 请求来测试是否有人能够登录我的站点。我在几个地方看到过这种推荐方式:
it 'must be able to sign in a user' do
user = create(:user)
post :create, format: :js, user: {email: user.email, password: user.password, remember_me: 0}
assert_response :success
@controller.current_user.must_equal user
end
但是这个测试是不正确的。调用 @controller.current_user
将尝试使用发布的参数对用户进行身份验证,如果提供的电子邮件/密码正确,将返回 user
。无法保证 create
操作实际上调用了 sign_in
或 current_user
。
即使我重新编写测试来检查是否调用了这些方法,也有可能调用其他方法,例如sign_out
。
是否有更明确的方法来最终检查用户是否已登录,如果是,用户是谁?
编辑 -
比如下面的测试会通过
it 'must sign in a user' do
@controller.current_user.must_equal nil
post :create, format: :js, user: {email: @user.email, password: @user.password, remember_me: 0}
assert_response :success
@controller.current_user.must_equal @user
end
当 SessionsController#create 操作是:
def create
respond_to do |format|
format.js {
render nothing: true, status: 200
}
end
end
最佳答案
对问题中建议的代码进行最少更改的解决方案:
您需要在测试开始前对系统进行初始化。尝试在您的 i t 'must be able to sign in a user' do
之前添加以下代码代码:
before (:each) do
user = FactoryGirl.create(:user)
sign_out user
end
这应该将您的测试变成对您的后 Controller 的有效测试。
解释:
我的假设是,您上面的测试总是成功的,因为用户已经登录(通过在此之前运行的其他测试)。您可以使用 byebug
来验证这一点在 it
之后的行中然后运行 current_user
在bybug's
安慰。如果不是 nil
,用户已经登录,这会使您的测试无效。
请注意,(与上面评论中讨论的内容不同),current_user
不改变用户的状态;它是一个只读函数。
更短/更清洁的解决方案:
在我看来,有一种更简洁的方法来执行这样的测试,如下所示:
def sign_in_via_post(user)
post :create, format: :js, user: {email: user.email, password: user.password, remember_me: 0}
end
...
before (:each) do
user = FactoryGirl.create(:user)
sign_out user
end
it 'must be able to sign in a user' do
{ sign_in_via_post user }.should change { current_user }.from(nil).to(user)
end
随着 should change from nil to user
语句,您验证用户在测试开始之前已注销,并且在执行测试后用户已登录。
注意,那部分
{ sign_in_via_post user }.should change { current_user }.from(nil).to(user)
相当于(可能更容易理解)代码
{ sign_in_via_post user }.should change { user_signed_in? }.from(false).to(true)
讨论 here .
关于ruby-on-rails - Rails 测试 - 检查用户是否使用 Devise 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39121841/