1

私は Rails Wisper gem を使用しており、特定のテスト (メール送信をテストする場所) でのみリスナー コールバック (メールを送信する) を実行したいと考えています。他のテストでは、本番環境でコールバックがメールを送信する場合でも、メールを送信したくありません。

ウィスパーで可能ですか?

パブリッシャー(app/models/order.rb)

class Order < ActiveRecord::Base
  include Wisper::Publisher

  after_save do
    publish(:order_after_save, self)
  end

end

リスナー/オブザーバー(アプリ/オブザーバー/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が、他のテストでは実行したくありません (多くの「注文」が作成され、通常はメール送信をトリガーするものが変更されます)。

RSpec をテスト フレームワークとして使用し、FactoryGirl を使用しています。

もちろんOrder、FactoryGirl で新しいインスタンスを作成するとメール送信がトリガーされますが、これも望ましくありません。

4

1 に答える 1

1

私は解決策を見つけました(より良い答えがあれば幸いです):

  1. config.before(:suite)テスト中に通知を受け取らないように、RSpec ブロックで問題のリスナーのサブスクライブを解除します。

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
  1. 選択したテストのリスナーのみをサブスクライブします。

仕様/オブザーバー/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このようにして、テスト中にパブリッシャー通知を 1 つだけ受け取ります。代わりに を使用letすると、2 つの通知create...が発生しorder.saveます。

于 2016-04-28T18:33:50.807 に答える