Rails Wisper跳过监听器回调

时间:2016-04-28 15:12:33

标签: ruby-on-rails rspec-rails wisper

我使用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实例会触发邮件,这也是不可取的。

1 个答案:

答案 0 :(得分:1)

我找到了一个解决方案(任何更好的答案将不胜感激):

  1. 在RSpec config.before(:suite)块中取消订阅有问题的侦听器 因此在测试期间不会收到任何通知。
  2. <强>规格/ 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
    
    1. 仅为选定的测试订阅侦听器。
    2. <强>规格/观察员/ 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引起。