在 Rails 方法中测试延迟作业邮件程序
Test delayed job mailers in Rails method
我有一个 rails 方法允许用户提交评论并向交易对手发送一封使用延迟作业的电子邮件。
def update_review
@review.add_review_content(review_params)
ReviewMailer.delay.review_posted(@review.product_owner, params[:id])
end
我正在尝试为此添加一个 rspec
测试,以检查邮件是否正确发送以及发送给谁。延迟的工作 运行 在 test
上创建后立即完成,因为我希望其他工作像更新产品所有者总体评级的工作立即完成。
所以电子邮件确实被触发了,但我如何为它添加测试?
编辑:添加当前测试
我目前的测试是:
describe 'PUT #update the review' do
let(:attr) do
{ rating: 3.0, raw_review: 'Some example review here' }
end
before(:each) do
@review = FactoryBot.create :review
put :update, id: @review.id, review: attr
end
it 'creates a job' do
ActiveJob::Base.queue_adapter = :test
expect {
AdminMailer.review_posted(@coach, @review.id).deliver_later
}.to have_enqueued_job
end
it { should respond_with 200 }
end
这确实测试了邮件程序是否正常工作,但我想测试它是否也在方法流程中被正确触发。
听起来您想要的是确保 update_review
方法将作业排入队列以将正确的电子邮件发送给正确的收件人。这是实现此目的的更简单方法:
describe 'PUT #update the review' do
let(:params) { { rating: rating, raw_review: raw_review } }
let(:rating) { 3.0 }
let(:raw_review) { 'Some example review here' }
let(:review) { FactoryBot.create(:review) }
let(:delayed_review_mailer) { instance_double(ReviewMailer) }
before do
# assuming this is how the controller finds the review...
allow(Review).to receive(:find).and_return(review)
# mock the method chain that enqueues the job to send the email
allow(ReviewMailer).to receive(:delay).and_return(delayed_review_mailer)
allow(delayed_review_mailer).to receive(:review_posted)
put :update, id: review.id review: params
end
it 'adds the review content to the review' do
review.reload
expect(review.rating).to eq(rating)
expect(review.raw_review).to eq(raw_review)
end
it 'sends a delayed email' do
expect(ReviewMailer).to have_received(:delay)
end
it 'sends a review posted email to the product owner' do
expect(delayed_review_mailer)
.to have_received(:review_posted)
.with(review.product_owner, review.id)
end
end
我更喜欢这种方法的原因是 a) 它可以在根本不接触数据库的情况下完成(通过将工厂换成双实例),并且 b) 它不会尝试测试 Rails 已经由构建 Rails 的人员测试过,例如 ActiveJob 和 ActionMailer。您可以信任 Rails 对那些 类.
自己的单元测试
我有一个 rails 方法允许用户提交评论并向交易对手发送一封使用延迟作业的电子邮件。
def update_review
@review.add_review_content(review_params)
ReviewMailer.delay.review_posted(@review.product_owner, params[:id])
end
我正在尝试为此添加一个 rspec
测试,以检查邮件是否正确发送以及发送给谁。延迟的工作 运行 在 test
上创建后立即完成,因为我希望其他工作像更新产品所有者总体评级的工作立即完成。
所以电子邮件确实被触发了,但我如何为它添加测试?
编辑:添加当前测试
我目前的测试是:
describe 'PUT #update the review' do
let(:attr) do
{ rating: 3.0, raw_review: 'Some example review here' }
end
before(:each) do
@review = FactoryBot.create :review
put :update, id: @review.id, review: attr
end
it 'creates a job' do
ActiveJob::Base.queue_adapter = :test
expect {
AdminMailer.review_posted(@coach, @review.id).deliver_later
}.to have_enqueued_job
end
it { should respond_with 200 }
end
这确实测试了邮件程序是否正常工作,但我想测试它是否也在方法流程中被正确触发。
听起来您想要的是确保 update_review
方法将作业排入队列以将正确的电子邮件发送给正确的收件人。这是实现此目的的更简单方法:
describe 'PUT #update the review' do
let(:params) { { rating: rating, raw_review: raw_review } }
let(:rating) { 3.0 }
let(:raw_review) { 'Some example review here' }
let(:review) { FactoryBot.create(:review) }
let(:delayed_review_mailer) { instance_double(ReviewMailer) }
before do
# assuming this is how the controller finds the review...
allow(Review).to receive(:find).and_return(review)
# mock the method chain that enqueues the job to send the email
allow(ReviewMailer).to receive(:delay).and_return(delayed_review_mailer)
allow(delayed_review_mailer).to receive(:review_posted)
put :update, id: review.id review: params
end
it 'adds the review content to the review' do
review.reload
expect(review.rating).to eq(rating)
expect(review.raw_review).to eq(raw_review)
end
it 'sends a delayed email' do
expect(ReviewMailer).to have_received(:delay)
end
it 'sends a review posted email to the product owner' do
expect(delayed_review_mailer)
.to have_received(:review_posted)
.with(review.product_owner, review.id)
end
end
我更喜欢这种方法的原因是 a) 它可以在根本不接触数据库的情况下完成(通过将工厂换成双实例),并且 b) 它不会尝试测试 Rails 已经由构建 Rails 的人员测试过,例如 ActiveJob 和 ActionMailer。您可以信任 Rails 对那些 类.
自己的单元测试