web-dev-qa-db-ja.com

メールが配信されたかどうかをRSpecでテストする方法

:postでコントローラーメソッドを呼び出した場合にメールが配信されるかどうかをテストしたいと思います。私はemail_specを使用するので、ここで切り詰めてみました: http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation

ただし、モデルオブジェクトのインスタンスをdelivery-methodに渡し、インスタンスは配信前に保存されるため、機能しません。

モデルオブジェクトの別のインスタンスを作成しようとしましたが、IDが同じではありません。

私のコントローラーメソッドは次のようになります。

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

これを解決するアイデアはありますか?

36
fossil12

テスト環境が通常の方法で設定されている(つまり、config.action_mailer.delivery_method = :testがある)と仮定すると、配信された電子メールはActionMailer::Base.deliveriesインスタンスとしてグローバル配列Mail::Messageに挿入されます。これをテストケースから読み取って、メールが期待どおりであることを確認できます。 こちら を参照してください。

56
Chowlett

送信されたメールをActionMailer::Base.deliveriesに蓄積するようにテスト環境を構成します。

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

次に、このようなもので、メールが送信されたことをテストできます。

# 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

この例ではRSpec 3構文を使用しています。

25
Dennis

私はこれでパーティーに遅れるのを知っていますが、将来のGoogle社員のために...

この問題のより良い解決策が答えられたと思います ここ

以前に受け入れられた答えは、メーラー自体(コントローラー仕様内)をテストすることです。ここでテストする必要があるのは、メーラーが正しいパラメーターで何かを配信するように指示されることだけです。

次に、メーラーを別の場所でテストして、これらのパラメーターに正しく応答することを確認できます。

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

19
Jules Copeland

参考までに、rspec 3.4とActiveJobを使用して非同期メールを送信するユーザーは、次のようにしてこれを確認できます。

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

これは、メイラーが正しい引数で呼び出されていることをテストする方法です。このコードは、機能、コントローラー、またはメーラーの仕様で使用できます。

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

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

もう少し追加するには、should_receiveを使用して呼び出しをスタブする場合は、他の場所で統合テストを行って、実際にメソッドを正しく呼び出していることを確認してください。

Should_receiveを使用して他の場所でテストされたメソッドを変更し、メソッド呼び出しが壊れた場合でもテストに合格することで、私は何度かビットを回ってきました。

Should_receiveを使用するよりも結果をテストしたい場合、shouldaには次のように機能するNiceマッチャーがあります。

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

Shouldaドキュメント

rSpecでShoulda Matcherを使用する方法の詳細

1
Jared

CapybaraCapybara Email と一緒に使用していて、 [email protected]、この方法も使用できます。

email = open_email('[email protected]')

そして、あなたはこのようにそれをテストすることができます:

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

試してみてください 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

その他の例: https://github.com/email-spec/email-spec#testing-in-isolation

0
Developer