2014-01-12 37 views
18

如何測試在我的郵件程序中使用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> 

回答

21

assigns只爲控制器規格定義而這通過RSpec的護欄寶石完成。沒有通用的機制來測試RSpec中的實例變量,但是您可以使用Kernel的instance_variable_get來訪問任何您想要的實例變量。

你的情況

所以,如果object是其實例變量,你有興趣在檢查對象,你可以寫:

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

至於得到阿霍德的UserMailer實例,我看不到任何方式要做到這一點。查看https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb中的method_missing定義,只要使用與實例方法相同的名稱調用未定義的類方法,就會創建一個新的郵件實例。但是這個實例並沒有保存在我能看到的任何地方,只返回了.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

so rspec rails不允許你在郵件程序中測試實例變量? Minitest確實... – pixelearth

+1

查看更新的答案。 –

+0

這很有用,除了在這種情況下,我不確定哪些對象會設置這些實例變量。有任何想法嗎? – pixelearth

2

我不認爲這是可能的測試,除非Rails的改變其執行因此它實際上提供對ActionMailer(控制器)對象的訪問權限,而不僅僅是生成的Mail對象。

正如彼得Alfvin指出,問題是,它返回 '消息' 在這裏:

new(method_name, *args).message 

,而不是隻返回郵件(控制器)是這樣的:

new(method_name, *args) 

post在rspec-rails列表中可能也會有幫助:

似乎合理,但不太可能改變。這是爲什麼。 rspec-rails 提供了圍繞由rails提供的測試類的包裝。 Rails 功能測試支持您上面提到的三個問題,但導軌 郵差測試是不同的。從 http://guides.rubyonrails.org/action_mailer_basics.html:「測試 郵寄者通常涉及兩件事:一是郵件排隊, 和另一個電子郵件是正確的。」

支持你想在郵件規格看什麼,RSpec的護欄將 必須提供它自己的ExampleGroup(而不是包裹軌 類),就必須緊緊結合軌道內部。 I 在rspec-rails-2中花費了很大的精力來限制與公共API 的耦合,並且這有很大的回報:我們只有一個例子,其中一個是 。x版本需要發佈rspec-rails(即有一個 重大更改)。使用rails-2,幾乎每個發行版都打破了rspec-rails ,因爲rspec-rails與內部連接(rspec-rails' fault,not rails)。

如果你真的想看到這個改變,你需要在rails自己改變 ,在這一點上rspec-rails會很高興地包裝新的 和改進的MailerTestCase。

相關問題