在测试中访问虚拟令牌

Accessing a virtual token in tests

在 Rails 教程第 8 章中测试了 'remember me' 复选框是否有效。

在真实比赛中,如果用户在登录页面选中 'remember me' 复选框,登录后会话控制器的创建操作将使用 remember(user) 助手,它会创建一个 remember_token 并更新用户模型中的 remember_digest 属性(通过 user.rb 中的 remember 方法),然后设置 cookies[:user_id] = user.idcookies[:remember_token] = user.remember_token.

书上说在考"Ideally, we would check that the cookie’s value is equal to the user’s remember token, but as currently designed there’s no way for the test to get access to it: the user variable in the controller has a remember token attribute, but (because remember_token is virtual) the @user variable in the test doesn’t"。

测试定义如下:

def setup
  @user = users(:michael)
end

test "login with remembering" do
  log_in_as(@user, remember_me: '1')
  assert_not_nil cookies['remember_token']
end

首先,考虑到cookies['remember_token']是如何定义的(cookies[:remember_token] = user.remember_token),如果我们确实无法访问remember token属性,我想知道我们如何检查cookies['remember_token'] 不为零。

虽然 fixtures 没有为用户 michael 定义任何记忆标记,log_in_as 测试助手方法被定义为 post 到 login_path params[:session] 的正确值,所以我想知道:这些值不是由会话控制器的创建操作采用的吗?如果是这种情况,那么 create 操作应该做与上面描述的真实比赛相同的工作:remember(user) 助手将为用户创建一个 remember_token,我们可以检查是否 cookies['remember_token'] = user.remember_token.

我不明白为什么我们不能访问 user.remember_token

@user 是通过夹具创建的。问题是,#remember_token 是一个虚拟属性,这意味着它不映射到数据库列。它仅在 #remember 函数在 User 实例上调用时才会设置,并且当该实例死亡时,它也会随之死亡(尽管它的摘要保存在数据库中,并且加密版本它保存在用户的 cookie 中。

你在那里使用 #log_in_as 所做的是,首先创建一个 User,然后在 #log_in_as 中获取该用户的电子邮件地址和密码,然后发送它到控制器。控制器使用您提供的电子邮件从数据库中找到该用户,然后继续调用该实例上的 #remember 函数。

如您所见,#remember 函数从未在您的 @user 实例上调用过,因此它从未收到 remember_token。但是通过该控制器操作,设置了一个 cookie 并将摘要保存在数据库中。所以你在那里测试的是检查cookie是否设置。

如果你想更细致一点,我想你可以做的另一件事是检查cookie的摘要是否与数据库中的摘要相同。