【问题标题】:Rails Wisper skip listener callbackRails Wisper 跳过侦听器回调
【发布时间】:2016-04-28 15:12:32
【问题描述】:

我使用 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。

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

【问题讨论】:

  • 展示你如何测试
  • 最好将监听器订阅到发布者的实例(例如order.subscribe(MailerOrderObserver.new))而不是全局订阅(例如Wisper.subscribe(MailerOrderObserver.new))。否则,您将遇到与常规 ActiveRecord 回调相同的问题(它们无法关闭)。

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


【解决方案1】:

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

  1. 在 RSpec config.before(:suite) 块中取消订阅有问题的侦听器 所以它不会在测试期间收到任何通知。

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. 仅为选定测试订阅监听器。

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

这样MailerOrderObserver 只有在测试前执行Wisper.subscribe... 时才会收到来自发布者的通知。

请注意,在订阅 Wisper 之前,使用 let!(带感叹号)来实例化 order 很方便。这样在测试期间只收到一个发布者通知。改用let 会导致两个通知:一个在create... 之后,一个由order.save 引起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多