Rails 4 +设计:如何在没有RSpec的情况下为Devise重置密码编写测试?

jus*_*dao 8 ruby-on-rails minitest devise ruby-on-rails-4

出于我无法控制的原因,我无法在当前项目中使用RSpec进行测试.我正在尝试测试Devise重置密码,我似乎无法想出一些有用的东西.

这是我到目前为止所拥有的:

require 'test_helper'

class ResetPasswordTest < ActionDispatch::IntegrationTest
  setup do
    @user = users(:example)
  end

  test "reset user's password" do 
    old_password = @user.encrypted_password

    puts @user.inspect

    # This assertion works
    assert_difference('ActionMailer::Base.deliveries.count', 1) do
      post user_password_path, user: {email: @user.email}
    end

    # puts @user.reset_password_token => nil
    # Not sure why this doesn't assign a reset password token to @user

    patch "/users/password", user: {
      reset_password_token: @user.reset_password_token, 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    # I get a success here, but I'm not sure why, since reset password token is nil.
    assert_response :success

    # This assertion doesn't work. 
    assert_not_equal(@user.encrypted_password, old_password)
  end

end
Run Code Online (Sandbox Code Playgroud)

我在上面添加了一些注释,似乎没有用.有没有人有一个洞察力,或者有关如何更好地测试这个的想法?

sea*_*cal 12

设计PasswordsController内部测试.我想PasswordsController用额外的功能测试我,然后去Devise的控制器测试,以帮助构建Devise默认功能的测试,然后将新功能的断言添加到测试用例中.

如其他答案所述,您必须获得reset_password_token.您可以使用与Devise相同的方式获取令牌,而不是像在另一个解决方案中解析已发送的电子邮件一样:

setup do
  request.env["devise.mapping"] = Devise.mappings[:user]
  @user = users(:user_that_is_defined_in_fixture)
  @reset_password_token  = @user.send_reset_password_instructions
end
Run Code Online (Sandbox Code Playgroud)

查看Devise的解决方案PasswordControllerTest:

https://github.com/plataformatec/devise/blob/master/test/controllers/passwords_controller_test.rb.

  • 这应该是可接受的答案,因为直接获取令牌而不是电子邮件解析更好。 (2认同)

jus*_*dao 8

我想通了,你需要在发送密码重置电子邮件以及何时重新加载用户put婷的/user/password路线.您还需要从电子邮件中获取密码令牌,因为它与存储在数据库中的密码令牌不同.

require 'test_helper'

class ResetPasswordTest < ActionDispatch::IntegrationTest
  setup do
    @user = users(:example)
  end

  test "reset user's password" do 
    # store old encrypted password
    old_password = @user.encrypted_password

    # check to ensure mailer sends reset password email
    assert_difference('ActionMailer::Base.deliveries.count', 1) do
      post user_password_path, user: {email: @user.email}
      assert_redirected_to new_user_session_path
    end

    # Get the email, and get the reset password token from it
    message = ActionMailer::Base.deliveries[0].to_s
    rpt_index = message.index("reset_password_token")+"reset_password_token".length+1
    reset_password_token = message[rpt_index...message.index("\"", rpt_index)]

    # reload the user and ensure user.reset_password_token is present
    # NOTE: user.reset_password_token and the token pulled from the email
    # are DIFFERENT
    @user.reload
    assert_not_nil @user.reset_password_token

    # Ensure that a bad token won't reset the password
    put "/users/password", user: {
      reset_password_token: "bad reset token", 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    assert_match "error", response.body
    assert_equal @user.encrypted_password, old_password

    # Valid password update
    put "/users/password", user: {
      reset_password_token: reset_password_token, 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    # After password update, signed in and redirected to root path
    assert_redirected_to root_path

    # Reload user and ensure that the password is updated.
    @user.reload
    assert_not_equal(@user.encrypted_password, old_password)
  end

end
Run Code Online (Sandbox Code Playgroud)


bob*_*lin 6

require 'rails_helper'

feature 'User' do
  let(:user) { create(:user) }
  let(:new_password) { 'Passw0rd!' }

  it 'reset password' do
    visit '/'

    click_link 'Forgot password?'
    fill_in 'E-mail', with: user.email

    expect do
      click_button 'Send me reset password instructions'
    end.to change(ActionMailer::Base.deliveries, :count).by(1)

    expect(unread_emails_for(user.email)).to be_present
    open_email(user.email, with_subject: 'Reset password instructions')
    click_first_link_in_email
    fill_in 'New password', with: new_password
    fill_in 'Confirm new password', with: new_password
    click_button 'Change password'

    expect(page).to have_notice 'Your password has changed'
    click_link 'Logout'

    fill_in 'E-mail', with: user.email
    fill_in 'Password', with: new_password

    click_button 'Sign in'
    expect(page).to have_notice 'Wellcome!'
  end
end
Run Code Online (Sandbox Code Playgroud)

此代码需要email_spec和FactoryGirl宝石.