web-dev-qa-db-fra.com

Comment tester avec RSpec si un e-mail est livré

Je voudrais tester si un e-mail est envoyé si j'appelle une méthode de contrôleur avec: post. Je vais utiliser email_spec donc j'ai essayé ceci coupé ici: http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation

Mais cela ne fonctionne pas, car je passe une instance de l'objet-modèle à la méthode de livraison et l'instance est enregistrée avant la livraison.

J'ai essayé de créer une autre instance de l'objet-modèle, mais l'ID n'est pas le même.

Ma méthode de contrôleur ressemble à ceci:

def create

   @params = params[:reservation]

   @reservation = Reservation.new(@params)
   if @reservation.save
      ReservationMailer.confirm_email(@reservation).deliver
      redirect_to success_path
   else
      @title = "Reservation"
      render 'new'
   end

end

Avez-vous une idée pour résoudre ce problème?

36
fossil12

En supposant que votre environnement de test est configuré de la manière habituelle (c'est-à-dire que vous avez config.action_mailer.delivery_method = :test), puis les e-mails envoyés sont insérés dans le tableau global ActionMailer::Base.deliveries comme Mail::Message les instances. Vous pouvez lire cela dans votre scénario de test et vous assurer que l'e-mail est conforme à vos attentes. Voir ici .

56
Chowlett

Configurez votre environnement de test pour accumuler les e-mails envoyés dans ActionMailer::Base.deliveries.

# config/environments/test.rb
config.action_mailer.delivery_method = :test

Ensuite, quelque chose comme ça devrait vous permettre de tester que le courrier a été envoyé.

# Sample parameters you would expect for POST #create.
def reservation_params
  { "reservation" => "Drinks for two at 8pm" }
end

describe MyController do
  describe "#create" do
    context "when a reservation is saved" do
      it "sends a confirmation email" do
        expect { post :create, reservation_params }.to change { ActionMailer::Base.deliveries.count }.by(1)
      end
    end
  end
end

Notez que mon exemple utilise la syntaxe RSpec 3.

25
Dennis

Je sais que je suis en retard à la fête avec celui-ci, mais pour les futurs Googlers ...

Je pense qu'une meilleure solution à ce problème est répondue ici

La réponse précédemment acceptée teste le Mailer lui-même (à l'intérieur des spécifications du contrôleur). Tout ce que vous devriez tester ici, c'est que le Mailer est invité à livrer quelque chose avec les bons paramètres.

Vous pouvez ensuite tester le Mailer ailleurs pour vous assurer qu'il répond correctement à ces paramètres.

ReservationMailer.should_receive (: confirm_email) .with (an_instance_of (Reservation))

19
Jules Copeland

Pour mémoire, à toute personne utilisant rspec 3.4 et ActiveJob pour envoyer des e-mails asynchrones, vous pouvez vérifier cela avec:

expect {
  post :create, params
}.to have_enqueued_job.on_queue('mailers')
5
Alter Lagos

Voici comment tester que Mailer est appelé avec les bons arguments. Vous pouvez utiliser ce code dans les spécifications de fonctionnalité, de contrôleur ou de mailer:

delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)

expect(ReservationMailer).to receive(:confirm_email)
  .with('reservation')
  .and_return(delivery)
4
boblin

Pour en ajouter un peu plus, assurez-vous que si vous voulez bloquer un appel à l'aide de should_receive, vous avez un test d'intégration ailleurs testant que vous appelez réellement la méthode correctement.

J'ai été un peu plusieurs fois en changeant une méthode qui a été testée ailleurs avec should_receive et en ayant toujours des tests réussis lorsque l'appel de méthode a été rompu.

Si vous préférez tester le résultat plutôt que d'utiliser should_receive, shoulda a un bon matcher qui fonctionne comme suit:

it { should have_sent_email.with_subject(/is spam$/) }

documentation Shoulda

Plus d'informations sur l'utilisation des Matchers Shoulda avec rSpec

1
Jared

Si vous utilisez Capybara avec Capybara Email et vous avez envoyé un e-mail à [email protected], vous pouvez également utiliser cette méthode:

email = open_email('[email protected]')

Et puis vous pouvez le tester comme ceci:

expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['[email protected]'])
1
GuilPejon

Essayez email-spec

describe "POST /signup (#signup)" do
  it "should deliver the signup email" do
    # expect
    expect(UserMailer).to(receive(:deliver_signup).with("[email protected]", "Jimmy Bean"))
    # when
    post :signup, "Email" => "[email protected]", "Name" => "Jimmy Bean"
  end
end

plus d'exemples ici: https://github.com/email-spec/email-spec#testing-in-isolation

0
Developer