2

モジュールをメーラーにミックスし、ビューでアクセスできるようにヘルパーとして追加しています。ビューから適切なヘルパーメソッドが呼び出されていることをテストする必要があります(追跡ピクセルが電子メールに含まれるようにするため)が、Rspecが機能していないようです:

require "spec_helper"

describe DeviseOverrideMailer do

  before :each do
    # Make the helper accessible.

    # This approach does not work
    # class MixpanelExposer; include MixpanelFacade end
    # @mixpanel = MixpanelExposer.new

    # This approach also does not seem to work, but was recommended here: http://stackoverflow.com/questions/10537932/unable-to-stub-helper-method-with-rspec
    @mixpanel = Object.new.extend MixpanelFacade
  end

  describe "confirmation instructions" do
    it "tells Mixpanel" do
      # Neither of these work.
      # DeviseOverrideMailer.stub(:track_confirmation_email).and_return('') 
      @mixpanel.should_receive(:track_confirmation_email).and_return('')

      @sender = create(:confirmed_user)
      @email = DeviseOverrideMailer.confirmation_instructions(@sender).deliver

    end
  end
end

メーラー:

class DeviseOverrideMailer < Devise::Mailer
  include MixpanelFacade
  helper MixpanelFacade
end

モジュール:

class MixpanelFacade
  def track_confirmation_email
    # Stuff to initialise a Mixpanel connection
    # Stuff to add the pixel
  end
end

メーラービュー(HAML):

-# Other HTML content

-# Mixpanel pixel based event tracking
- if should_send_pixel_to_mixpanel?
  = track_confirmation_email @resource

エラー:Mixpanel接続を適切に初期化できない(リクエストヘルパーがないため)と文句を言います。これは、.should_receive()がtrack_confirmation_email()メソッドを正しくスタブアウトしていないことを示しています。どうすれば正しくスタブアウトできますか?

4

2 に答える 2

1

Rails は、Mailer のインスタンスを公開しないことで、これを難しくしています。メーラーでインスタンス メソッドを定義する方法に注意してください。たとえば、def confirmation_instructions(sender) ...so: のようにクラス メソッドとして呼び出しますDeviseOverrideMailer.confirmation_instructions(@sender)。これはいくつかのmethod_missing魔法によって可能になります:

# actionmailer-3.2.11/lib/action_mailer/base.rb 
module ActionMailer
  #...
  class Base < AbstractController::Base
    #...
    class << self
      #...
      #line 437
      def method_missing(method, *args) #:nodoc:
        return super unless respond_to?(method)
        new(method, *args).message
      end

によって作成された使い捨てインスタンスに注意してくださいnew(...).message。私たちのメーラーはインスタンス化され、使用され、破棄されるため、モック/スタブのために仕様からインターセプトする簡単な方法はありません。

私が提案できる唯一のことは、スタブしたい動作を別のクラス メソッドに抽出し、それをスタブすることです。

# in the helper:
module MixpanelFacade
  def track_confirmation_email
    Utils.track_confirmation_email(@some_state)
  end

  module Utils
    def self.track_confirmation_email(some_param)
      # Stuff to initialise a Mixpanel connection
      # Stuff to add the pixel
    end
  end
end

# in the spec
it "tells Mixpanel" do
  MaxpanelFacade::Utils.stub(:track_confirmation_email).and_return('') 
  @sender = create(:confirmed_user)
  @email = DeviseOverrideMailer.confirmation_instructions(@sender).deliver
end

これは確かにハックです - スタブできるように、不要なクラス メソッドを抽出しています - しかし、それを行う他の方法に出くわしたことはありません。これをまだ解決していない場合は、rspec メーリング リストで質問する価値があります (彼らの意見を教えてください :)。

于 2013-02-12T16:14:45.603 に答える