2012-03-27 8 views
8

Ich habe eine ActionMailer KlasseActionmethodenaufruf nil in Modul Rückkehr während rspec Test

class UserMailer < ActionMailer::Base 
    default from: "[email protected]" 

    def submission_reminder user 
    @user = user   
    mail :to => user.email, :subject => "Your timesheet needs to be submitted!" 
    end  
end 

Wenn ich rufe UserMailer.submission_reminder(current_user) in Entwicklung es gibt mir ein Mail::Message Objekt wie erwartet.

Der Platz in meiner Anwendung, wo diese Methode aufgerufen wird in einem Modul, das ich in den Ordner lib haben:

module TimesheetSubmissionNotifier        
    def self.send_submission_reminders 
    User.all.each { |user| UserMailer.submission_reminder(user).deliver } 
    end 
end 

Als ich TimesheetSubmissionNotifier.send_submission_reminders in Entwicklung nennen, UserMailer.submission_remind (Benutzer) gibt die Mail-Nachricht und Liefern heisst, alles funktioniert wie es soll.

Das Problem ist, wenn ich TimesheetSubmissionNotifier.send_submission_reminders durch einen RSPEC-Test aufrufen, gibt UserMailer.submission_reminder(user) NULL zurück.

Wenn ich UserMailer.submission_reminder(user) direkt von einem RSPECT-Test aufrufen, wird die Mailer-Nachricht wie erwartet zurückgegeben.

Hier sind die einzigen Linien Action Zusammenhang in meiner config/environment/test.rb:

config.action_mailer.delivery_method = :test 
config.action_mailer.default_url_options = { :host => 'localhost:3000' } 

Irgendwelche Ideen, warum die Methode zurückgibt nil?

+0

Wenn Sie sagen, 'UserMailer inmission_reminder (user)' direkt aus einem rspec-Test zu verwenden, wie initialisieren Sie das Objekt ** user **, das Sie an die Methode übergeben? Sie erhalten es aus der Tabelle Benutzer oder Sie bauen es mit einer Factory, etc.? – Zheileman

Antwort

16

Für diejenigen, die ein ähnliches Problem haben, habe ich das Problem gefunden.

Ich habe die RSpec-Erwartung should_receive verwendet, die ich nicht realisiert habe, tatsächlich erstellt ein Mock der Klasse, auf die es gelegt wird. Also habe ich mich über die UserMailer-Klasse lustig gemacht, was bedeutete, dass sie niemals die eigentliche UserMailer-Klasse erreichte.

ich es nicht mit Hilfe der Mock-Funktionen arbeitet bekommen konnte, so stattdessen änderte ich meinen Test am UserMailer.deliveries Speicher zu schauen und prüfen, ob die richtige Menge an Nachrichten in dort gesetzt wird und dass sie nach rechts gesendet werden E-mailadressen.

+1

Ja, ich habe das auch gemacht, es gibt ein einfaches Google-Beispiel, das das tut. Es ist wert, die Leute zu warnen, dass dies eine sehr falsche Möglichkeit ist, das zu testen. Should_receive verspottet einen Methodenendpunkt, definiert aber keine Art von Rückgabewert, es sei denn, Sie tun dies explizit (der Empfang hat nichts mit dem Empfang von E-Mails zu tun ;-)). –

+1

Technisch gesehen erzeugt should_receive kein Mock-Objekt, es stubbt die Methode aus und gibt nil zurück (rspec docs bezeichnet dies als partiellen Mock). Mit and_call_original können Sie die ursprüngliche Methode aufrufen. z.B. should_receive (: submission_reminder) .und_call_original –

+3

Wir haben dieses Upgrade auf Rails 4 durchgeführt. Wir haben sidekiq delay verwendet, das sich während des Upgrades geändert hat, um einen RuntimeError auszulösen, der ein nicht zustellbares E-Mail-Objekt zurückgab, wenn der Mailer null zurückgibt. Mailer.should_receive (: submission_reminder) .and_call_original hat die Tests repariert. –