2016-04-28 107 views
0

我使用Rails Wisper gem,並且只在特定測試(我測試電子郵件發送的地方)期間執行監聽器回調(發送電子郵件)。在其他測試中,即使在生產中我的回調會發送郵件,我也不想發送電子郵件。Rails Wisper跳過監聽器回調

Wisper有可能嗎?

出版商(應用程序/模型/ 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 

訂閱(配置/初始值設定項/ wisper.rb)

Rails.application.config.to_prepare do 
    Wisper.clear if Rails.env.development? || Rails.env.test? 
    # add observers 
    Wisper.subscribe(MailerOrderObserver.new) 
end 

測試(規格/觀察員/ 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 

我測試上面我想執行MailerOrderObserverorder_after_save回調,但不是在任何其他測試(很多「訂單」創建和修改了什麼通常會觸發電子郵件發送)。

我使用RSpec作爲測試框架和FactoryGirl。

當然,使用FactoryGirl創建新的Order實例觸發郵件,這也是不希望的。

+0

顯示如何測試 –

+0

您最好將訂閱服務器的發佈者實例(如'order.subscribe(MailerOrderObserver.new)')而不是全局訂閱(即Wisper.subscribe(MailerOrderObserver.new) ')。否則,您只會遇到與常規ActiveRecord回調相同的問題(它們無法關閉)。 – Kris

回答

0

我找到了解決方案(沒有更好的答案可以理解):

  1. 退訂聽衆在提問中的RSpec 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之前,爲了實例化order,使用let!(帶感嘆號)很方便。這樣在測試過程中只收到一個發佈者通知。相反,使用let將導致兩個通知:一個在create...之後,另一個由order.save造成。