【问题标题】:How to test for successful password change?如何测试密码更改是否成功?
【发布时间】:2012-10-16 17:01:22
【问题描述】:

我已经使用bcrypt-rubyhas_secure_password 组合了一个带有用户身份验证的基本应用程序。结果本质上是来自Rails Tutorial 的应用程序的准系统版本。换句话说,我有一个 RESTful 用户模型以及登录和注销功能。

作为编辑用户信息的测试的一部分,我编写了一个更改密码的测试。虽然更改密码在浏览器中工作得很好,但我下面的测试没有通过。

subject { page }

describe "successful password change"
  let(:new_password) { "foobaz" }
  before do
    fill_in "Password",               with: new_password
    fill_in "Password Confirmation",  with: new_password
    click_button "Save changes"
  end

  specify { user.reload.password.should == new_password }
end

显然,我在这里误解了一些基本细节。

简而言之:

1) 为什么上面的代码不起作用?更改密码功能在浏览器中工作。同时,rspec 继续重新加载上面最后一行中的旧密码。然后测试失败。

2) 测试密码更改的更好方法是什么?

编辑:

初始密码设置为foobar,错误信息为:

Failure/Error: specify { user.reload.password.should == new_password }
   expected: "foobaz"
        got: "foobar" (using ==)

基本上,before 块似乎并未真正保存新密码。

供参考,相关控制器动作如下:

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    flash[:success] = "Profile Updated"
    sign_in @user
    redirect_to root_path
  else
    render 'edit'
  end
end

【问题讨论】:

  • 我注意到规范中的user 是一个局部变量——你在哪里定义的?您是否也为此使用了let
  • @lain 是的,就在上面几行我用letFactoryGirl 创建了一个用户。
  • @veritas1 我已添加错误消息以供参考。
  • 对于任何有兴趣的人,有一个类似的老问题here 的答案,这似乎不适用于我的情况。
  • 还有一个类似的问题here。也许这是一个 rspec 错误??

标签: ruby-on-rails ruby-on-rails-3 rspec rspec-rails railstutorial.org


【解决方案1】:

对于 Devise 用户,请改用 #valid_password?

expect(user.valid_password?('correct_password')).to be(true)

信用:Ryan Bigg

【讨论】:

  • 如果您在更改密码后进行渲染,则与其他示例一样,您需要在调用和测试valid_password? 之前执行user.reload。如果您正在重定向,您显然需要在重定向页面中测试assigns[:user] 或等效项。
【解决方案2】:

这里一个不太令人满意的解决方案是使用bcrypt-ruby提供的#authenticate方法编写一个测试。

specify { user.reload.authenticate(new_password).should be_true }

当然,这不是一个合适的集成测试,但它会让我们变绿。

【讨论】:

【解决方案3】:

您的答案(使用authenticate)是正确的方法;你应该对此感到满意。您想比较模型中密码的散列版本而不是 @password(通过 attr_accessor)。请记住,您保存的是哈希而不是实际密码。

您在测试中的user 是该用户在内存中的副本。当您运行测试时,更新方法会在内存中加载该用户的不同副本并更新其保存到数据库的密码哈希。你的副本没有改变;这就是为什么您想重新加载以从数据库中获取更新的数据。

密码字段不存储在数据库中,而是存储为散列,因此新的散列会从数据库中重新加载,但是您正在比较 user 实例中 @password 的短暂状态而不是加密密码。

【讨论】:

    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 2019-01-12
    • 2017-12-08
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    相关资源
    最近更新 更多