web-dev-qa-db-ja.com

メーラーでrspecを使用してインスタンス変数が設定されていることをテストするにはどうすればよいですか?

メーラーでrspecを使用して特定のインスタンス変数が設定されていることをテストするにはどうすればよいですか?割り当ては未定義で戻ってきます。

require File.dirname(__FILE__) + '/../../spec_helper'

describe UserMailer do

  it "should send the member user password to a User" do
    user = FG.create :user

    user.create_reset_code

    mail = UserMailer.reset_notification(user).deliver

    ActionMailer::Base.deliveries.size.should == 1  

    user.login.should be_present  

    assigns[:person].should == user
    assigns(:person).should == user #both assigns types fail
  end
end

返されるエラーは次のとおりです。

undefined local variable or method `assigns' for #<RSpec::Core::ExampleGroup::Nested_1:0x007fe2b88e2928>
18
pixelearth

assignscontroller仕様に対してのみ定義されており、それはrspec-Rails gemを介して行われます。 RSpecでインスタンス変数をテストする一般的なメカニズムはありませんが、カーネルのinstance_variable_getを使用して、必要なインスタンス変数にアクセスできます。

したがって、あなたの場合、objectがインスタンス変数を確認したいオブジェクトである場合、次のように書くことができます。

expect(object.instance_variable_get(:@person)).to eql(user)

UserMailerインスタンスを取得することに関しては、私はそれを行う方法を見つけることができません。内部のmethod_missing定義 https://github.com/Rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb を見ると、新しいメーラーインスタンスが作成されます未定義のクラスメソッドがインスタンスメソッドと同じ名前で呼び出された場合。しかし、そのインスタンスは私が見ることができる場所には保存されず、.messageの値のみが返されます。以下は、現在githubで定義されている関連コードです。

クラスメソッド:

  def respond_to?(method, include_private = false) #:nodoc:
    super || action_methods.include?(method.to_s)
  end

  def method_missing(method_name, *args) # :nodoc:
    if respond_to?(method_name)
      new(method_name, *args).message
    else
      super
    end
  end

インスタンスメソッド:

attr_internal :message

# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
# will be initialized according to the named method. If not, the mailer will
# remain uninitialized (useful when you only need to invoke the "receive"
# method, for instance).
def initialize(method_name=nil, *args)
  super()
  @_mail_was_called = false
  @_message = Mail.new
  process(method_name, *args) if method_name
end

def process(method_name, *args) #:nodoc:
  payload = {
    mailer: self.class.name,
    action: method_name
  }

  ActiveSupport::Notifications.instrument("process.action_mailer", payload) do
    lookup_context.skip_default_locale!

    super
    @_message = NullMail.new unless @_mail_was_called
  end
end
22
Peter Alfvin

Railsが実装を変更して、生成されたMailオブジェクトだけでなく、ActionMailer(コントローラー)オブジェクトへのアクセスを実際に提供しない限り、これをテストすることはできないと思います。

Peter Alfvinが指摘したように、問題はここに「メッセージ」を返すことです。

new(method_name, *args).message

次のようにメーラー(コントローラー)を返すだけではありません。

new(method_name, *args)

Rspec-Railsリストにある post も役立つかもしれません。

妥当と思われますが、変更される可能性はほとんどありません。これが理由です。 rspec-Railsは、Railsによって提供されるテストクラスのラッパーを提供します。 Rails機能テストは上記の3つの質問をサポートしますが、Railsメーラーテストは異なります。から http://guides.rubyonrails.org /action_mailer_basics.html :「通常、メーラーのテストには2つのことが含まれます。1つはメールがキューに入れられたこと、もう1つはメールが正しいことです。」

メーラーの仕様で確認したい内容をサポートするには、rspec-Railsが独自のExampleGroupを提供する必要があります(Railsクラスをラップするのではなく))。これはRailsに緊密にバインドする必要があります'internals。公開APIへの結合を制限するためにrspec-Rails-2に多大な労力を費やしましたが、これには大きな見返りがありました。Rails 3.xリリースにはrspec-Railsのリリースが必要でした(つまり、重大な変更がありました)。Rails-2では、rspec-Railsが内部に関連付けられているため(Railsではなく、rspec-Railsの障害)、ほとんどのリリースでrspec-Railsが壊れました。

本当にこの変更を確認したい場合は、Rails自体で変更する必要があります。この時点で、rspec-Railsは新しい改良されたMailerTestCaseを適切にラップします。

3
Tyler Rick