1

我使用 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回调,但不是在任何其他测试中(创建了许多“订单”并更改了通常会触发电子邮件发送的内容)。

我使用 RSpec 作为测试框架和 FactoryGirl。

当然Order,使用 FactoryGirl 创建新实例会触发邮件,这也是不希望的。

4

1 回答 1

1

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

  1. 在 RSpecconfig.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
  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...

请注意,使用let!(带有感叹号)以便order在订阅 Wisper 之前进行实例化很方便。这样在测试期间只收到一个发布者通知。使用letinstead 将导致两个通知:一个 aftercreate...和一个由order.save.

于 2016-04-28T18:33:50.807 回答