I try to test a model. After the model under test is created, it creates an object from another model and sends out an email based on the other object's ID.
# model under test
class AccountabilityBuddy < ApplicationRecord
after_save_commit :send_consent_inquiry
def send_consent_inquiry
consent_tracker = BuddyConsent.create!(accountability_buddy_id: self.id)
BuddyMailer.with(buddy: self, consent_link: consent_tracker.id).buddy_request.deliver_later
end
...
This is what I've tried so far:
# the model test
RSpec.describe AccountabilityBuddy, type: :model do
subject(:buddy) { build(:accountability_buddy) }
describe 'after_save callback' do
let(:saving) do
buddy.save!
buddy.reload
end
it 'sends an email to the buddy' do
# how that works: https://stackoverflow.com/questions/22988968/testing-after-commit-with-rspec-and-mocking/30901628#comment43748375_22989816
expect { saving }
.to have_enqueued_job(ActionMailer::MailDeliveryJob)
.with('BuddyMailer', 'buddy_request', 'deliver_now', params: {buddy: buddy, consent_link: BuddyConsent.last.id }, args: [])
# Test fails, BuddyConsent.last.id is nil
end
it 'creates a new BuddyConsent' do
expect { saving }.to(change { BuddyConsent.all.count }.from(0).to(1))
# Test passes
end
end
...
The first test fails because the BuddyConsent.last.id is nil. I know that BuddyConsent
is generated correctly, because the ID is available inside the let
block:
let(:saving) do
buddy.save!
buddy.reload
BuddyConsent.last.id # => "8be42055-112c-4ba6-bd1b-61b73946fb6e"
end
How do I make it available inside the matcher and why is it out of context?
Aucun commentaire:
Enregistrer un commentaire