# Poor specs
# ==========
describe CloseOrder do
# Testing #call using partial double of object being tested
# looks unnatural and feels as a duplication
describe '#call' do
it do
order = create(:order)
service = CloseOrder.new(order)
allow(service).to receive(:send_notification)
service.call
expect(service).to have_received(:send_notification)
end
end
describe '#send_notification' do
it 'delivers order closed notification to customer' do
order = create(:order, customer_email: 'tony@stark.com')
service = CloseOrder.new(order)
expect {
service.send(:send_notification) # We are forced to use #send to test private method
}.to change { ActionMailer::Base.deliveries.count }.by(1)
notification = ActionMailer::Base.deliveries.last
expect(notification).to have_attributes(subject: 'Order closed!', recipients: ['tony@stark.com'])
end
end
end
# Good specs
# ==========
describe CloseOrder do
describe '#call' do
it 'delivers order closed notification to customer' do
order = create(:order, customer_email: 'tony@stark.com')
service = CloseOrder.new(order)
expect {
service.call
}.to change { ActionMailer::Base.deliveries.count }.by(1)
notification = ActionMailer::Base.deliveries.last
expect(notification).to have_attributes(subject: 'Order closed!', recipients: ['tony@stark.com'])
end
end
end
# Implementation
# ==============
class CloseOrder
def initialize(order)
@order = order
end
def call
send_notification
end
private
def send_notification
OrderMailer.order_closed_notification(@order).deliver_now
end
end