如何在 Rails 5 中使用 Capybara 和 Minitest 测试密码重置邮件程序
How to test a password reset mailer with Capybara and Minitest in Rails 5
我在 Rails 中使用许可 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
您如何实际测试邮件是否已正确发送?有没有办法模拟水豚点击电子邮件中的密码重置 link,然后填写表格以重置密码?
我也试过了,但是这条线失败了,所以我显然做错了什么:
assert_equal 1, ActionMailer::Base.deliveries.size
我可以通过从服务器日志中获取密码重置电子邮件 link 来手动测试,因此该功能可以正常工作。
我可以在网上找到的所有示例都假设您使用的是 Rspec,但 Minitest 没有。我也尝试使用 capybara-email gem,但没有 Minitest 示例,我也无法使用它。
供参考:
Gemfile
test_helper.rb
为了自己想做的事capybara-email
是不错的选择。要设置它,您可以将它包含在 ActionDispatch::IntegrationTest
中或包含在需要它的单独测试 class 中(在您当前的情况下 - 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...
- 您通常更喜欢前者,因为后者没有 waiting/retrying 行为并且可能导致不稳定的测试。另请注意,如果您想更改路径名,那么编写在路径名中硬编码的测试会导致一场噩梦,因此您最好使用 rails 提供的路由助手来编写代码
assert_current_path(login_path)
等等
我在 Rails 中使用许可 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
您如何实际测试邮件是否已正确发送?有没有办法模拟水豚点击电子邮件中的密码重置 link,然后填写表格以重置密码?
我也试过了,但是这条线失败了,所以我显然做错了什么:
assert_equal 1, ActionMailer::Base.deliveries.size
我可以通过从服务器日志中获取密码重置电子邮件 link 来手动测试,因此该功能可以正常工作。
我可以在网上找到的所有示例都假设您使用的是 Rspec,但 Minitest 没有。我也尝试使用 capybara-email gem,但没有 Minitest 示例,我也无法使用它。
供参考: Gemfile test_helper.rb
为了自己想做的事capybara-email
是不错的选择。要设置它,您可以将它包含在 ActionDispatch::IntegrationTest
中或包含在需要它的单独测试 class 中(在您当前的情况下 - 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...
- 您通常更喜欢前者,因为后者没有 waiting/retrying 行为并且可能导致不稳定的测试。另请注意,如果您想更改路径名,那么编写在路径名中硬编码的测试会导致一场噩梦,因此您最好使用 rails 提供的路由助手来编写代码
assert_current_path(login_path)
等等