我使用Rails Wisper gem并且我想在特定测试期间(我测试电子邮件发送的地方)执行监听器回调(它发送电子邮件)。在其他测试中,我不想发送电子邮件,即使在生产中我的回调会发送它们。
Wisper可以吗?
发布商(app / models / order.rb)
class Order < ActiveRecord::Base
include Wisper::Publisher
after_save do
publish(:order_after_save, self)
end
end
监听/观察员(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
订阅(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
测试(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
我上面的测试我要执行MailerOrderObserver
order_after_save
回调,但不能执行任何其他测试(许多&#34;订单&#34;创建和更改通常会触发电子邮件发送的内容)
我使用RSpec作为测试框架和FactoryGirl。
当然,使用FactoryGirl创建新的Order
实例会触发邮件,这也是不可取的。
答案 0 :(得分:1)
我找到了一个解决方案(任何更好的答案将不胜感激):
config.before(:suite)
块中取消订阅有问题的侦听器
因此在测试期间不会收到任何通知。<强>规格/ 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
<强>规格/观察员/ 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
这种方式MailerOrderObserver
仅在测试前执行Wisper.subscribe...
时才会收到发布者的通知。
请注意,在订阅Wisper之前使用let!
(带感叹号)以便实例化order
很方便。这样,在测试期间只收到一个发布者通知。使用let
会导致两个通知:一个在create...
之后,一个由order.save
引起。