I use Rails Wisper gem and I want to execute listener callback (which sends email) only during specific tests (where I test email sending). In other tests I don't want to send emails even if in production my callback would send them.
Is it possible with Wisper?
publisher (app/models/order.rb)
class Order < ActiveRecord::Base
include Wisper::Publisher
after_save do
publish(:order_after_save, self)
end
end
listener/observer (app/observers/mailer_order_observer.rb)
class MailerOrderObserver
def order_after_save order
if order.status_id_changed? && order.status.notify?
# send email
end
end
end
subscription (config/initializers/wisper.rb)
Rails.application.config.to_prepare do
Wisper.clear if Rails.env.development? || Rails.env.test?
# add observers
Wisper.subscribe(MailerOrderObserver.new)
end
test (spec/observers/mailer_order_observer_spec.rb)
require 'spec_helper'
describe MailerOrderObserver, type: :model do
let (:order) { create(:order, :with_items) }
it 'should send email' do
order.status = create(:status_released)
# emails are handled by external service, line below just triggers
# sending
expect(order.save).to eq(true)
end
end
I the test above I want to execute MailerOrderObserver
order_after_save
callback, but not in any other tests (many "orders" are created and changed what normally would trigger email sending).
I use RSpec as testing framework and FactoryGirl.
Of course creating new Order
instances with FactoryGirl triggers mailing, which is also not desired.
I found a solution (any better answer will be appreciated):
config.before(:suite)
block so it won't receive any notifications during the tests.spec/spec_helper.rb
RSpec.configure do |config|
config.before(:suite) do
# unsubscribe observer
Rails.application.config.to_prepare do
Wisper.unsubscribe(MailerOrderObserver.new)
end
end
end
spec/observers/mailer_order_observer_spec.rb
require 'spec_helper'
describe MailerOrderObserver, type: :model do
# ! prevents lazy loading
let! (:order) { create(:order, :with_items) }
describe '.order_after_save' do
before do
Wisper.subscribe(MailerOrderObserver.new)
end
it 'should send email' do
order.status = create(:status_released)
expect(order.save).to eq(true)
end
end
end
This way MailerOrderObserver
receives notifications from publisher only when Wisper.subscribe...
is executed before the test.
Note that it is convenient to use let!
(with exclamation mark) in order to instantiate order
before subscribing to the Wisper. This way only one publisher notification is received during test. Using let
instead will cause two notifications: one after create...
and one caused by order.save
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.