1

我在 Rails 中使用 Clearance gem 以及 Capybara 和 Minitest,但我不知道如何测试密码重置邮件。我不想测试已经经过良好测试的 Clearance gem,但我想要一个高级集成测试以确保不会破坏预期的用户体验,其中包括邮件程序。

这是我无法完成的测试(/integration/password_reset_test.rb):

require 'test_helper'

class PasswordResetTest < ActionDispatch::IntegrationTest

  def setup
    ActionMailer::Base.deliveries.clear
    @user   = create(:user)
  end

  test "User can reset their password" do
    visit "/login"
    assert page.current_path == "/login"
    click_link "Forgot password?"
    assert page.current_path == "/passwords/new"
    assert_selector "h1", text: "Reset your password"
    fill_in("Email", :with => @user.email)
    click_button "Reset your password"
    assert page.current_path == "/passwords"
    assert_selector "h1", text: "Your password reset email is on the way."
    # This is where I'm stuck
    # Would like to test that the correct email was sent by checking
    #      basic content in the email and then simulate a user clicking
    #      the password reset link and then updating their password.
  end
end

您如何实际测试邮件是否正确发送,有没有办法模拟水豚点击电子邮件中的密码重置链接,然后填写表格以重置密码?

我也试过这个,但是这条线失败了,所以我显然没有做对:

assert_equal 1, ActionMailer::Base.deliveries.size

我可以通过从服务器日志中获取密码重置电子邮件链接来手动测试,因此该功能可以正常工作。

我可以在网上找到的所有示例都假设您使用的是 Rspec,但对于 Minitest 则没有。我也尝试使用capybara-email gem,但没有 Minitest 示例,我也无法使其正常工作。

供参考: Gemfile test_helper.rb

4

1 回答 1

3

对于你想做的事情capybara-email是一个不错的选择。要设置它,您可以将它包含ActionDispatch::IntegrationTest在需要它的单个测试类中(在您当前的情况下 - PasswordResetTest)。您很可能还需要配置 ActiveJob 以在它们排队时执行作业,而不是延迟它们(否则实际上不会发送电子邮件)。一种方法是包含ActiveJob::TestHelper然后使用perform_enqueued_jobs它提供的方法。这导致了一些类似的事情

require 'test_helper'

class PasswordResetTest < ActionDispatch::IntegrationTest
  include Capybara::Email::DSL
  include ActiveJob::TestHelper

  def setup
    clear_emails
    @user   = create(:user)
  end

  test "User can reset their password" do
    perform_enqueued_jobs do
      visit "/login"
      assert_current_path("/login")
      click_link "Forgot password?"
      assert_current_path("/passwords/new")
      assert_selector "h1", text: "Reset your password"
      fill_in("Email", :with => @user.email)
      click_button "Reset your password"
      assert_current_path("/passwords")
      assert_selector "h1", text: "Your password reset email is on the way."
    end
    open_email(@user.email)
    assert_content(current_email, 'blah blah')
    current_email.click_link('Reset Password')
    assert_current_path(reset_password_path)
    ...  # fill out form with new password, etc.
  end
end

注意使用assert_current_path而不是assert page.current_path...- 您通常更喜欢前者,因为后者没有等待/重试行为并且可能导致不稳定的测试。另请注意,如果您想更改路径名称,那么编写在路径名称中硬编码的测试会导致一场噩梦,因此您最好使用 rails 提供的路线帮助程序来编写代码

assert_current_path(login_path)

等等

于 2018-04-03T18:13:33.560 回答