2014-01-12 10 views
18

rspecを使用して自分のメーラーに特定のインスタンス変数が設定されていることをテストするにはどうすればよいですか?未定義戻ってくる。..rspecを使用してmy mailerにインスタンス変数が設定されていることをテストするにはどうすればよいですか?

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> 

答えて

21

assignsのみコントローラ仕様のために定義され、そのは、RSpecのレールの宝石を介して行われます。 RSpecでインスタンス変数をテストする一般的なメカニズムはありませんが、Kernelのinstance_variable_getを使用して、必要なインスタンス変数にアクセスできます。

objectは、そのインスタンス変数あなたがチェックに興味を持っていた物だったのであれば、あなたの場合には、あなたが書くことができる:UserMailerインスタンスのネタを取得するためとして

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

、私はどのような方法を見ることができませんそれをする。 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 
+0

rspec railsではメーラのインスタンス変数をテストできません。 Minitestは... – pixelearth

+1

更新された回答を参照してください。 –

+0

これは便利ですが、この場合を除いて、私はどのオブジェクトがそれらのインスタンス変数を設定するのかはわかりません。何か案は? – pixelearth

2

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

new(method_name, *args) 

このpost:ちょうどこのようなメーラー(コントローラ)を返すのではなく、

new(method_name, *args).message 

:ピーターAlfvinが指摘したように

は、問題は、それがここで 'メッセージ' を返すということです

rspec-railsのリストは、参考になるかもしれませんが、変更はほとんどありません。理由は次のとおりです。 rspec-rails は、レールによって提供されるテストクラスの周りにラッパーを提供します。レール 上記の3つの質問を機能テストでサポートしていますが、レール のメーラテストは異なります。 http://guides.rubyonrails.org/action_mailer_basics.htmlから: " メールをテストするには、通常、メールがキューに入れられたことと、 とメールが正しいことが含まれます。

あなたはメーラーの仕様に見たいものをサポートするために、RSpecのレールは は、それ自身のExampleGroupを提供(というよりもレール クラスラップ)しっかりとRailsの内部にバインドしなければならないであろう、しなければなりません。私は はrspec-rails-2で公開の APIへの結合を制限するために大きな苦労をしました。これは大きな利益をもたらしました。 が3つの場合しかありませんでした。xリリースでは、rspec-railsのリリースが必要でした(つまり、変更があったのは でした)。 rails-2では、rspec-railsが内部(rspec-rails ' 障害、レールではない)に結びついていたため、ほぼすべてのリリースで rspec-railsが壊れました。

本当にこの変更を確認したい場合、あなたはそれがRSpecのレールは喜んで新しい をラップする、その時点でレール自体に を変更し、MailerTestCaseを改善取得する必要があります。

関連する問題