: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
これを解決するアイデアはありますか?
テスト環境が通常の方法で設定されている(つまり、config.action_mailer.delivery_method = :test
がある)と仮定すると、配信された電子メールはActionMailer::Base.deliveries
インスタンスとしてグローバル配列Mail::Message
に挿入されます。これをテストケースから読み取って、メールが期待どおりであることを確認できます。 こちら を参照してください。
送信されたメールを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構文を使用しています。
私はこれでパーティーに遅れるのを知っていますが、将来のGoogle社員のために...
この問題のより良い解決策が答えられたと思います ここ
以前に受け入れられた答えは、メーラー自体(コントローラー仕様内)をテストすることです。ここでテストする必要があるのは、メーラーが正しいパラメーターで何かを配信するように指示されることだけです。
次に、メーラーを別の場所でテストして、これらのパラメーターに正しく応答することを確認できます。
ReservationMailer.should_receive(:confirm_email).with(an_instance_of(Reservation))
参考までに、rspec 3.4とActiveJobを使用して非同期メールを送信するユーザーは、次のようにしてこれを確認できます。
expect {
post :create, params
}.to have_enqueued_job.on_queue('mailers')
これは、メイラーが正しい引数で呼び出されていることをテストする方法です。このコードは、機能、コントローラー、またはメーラーの仕様で使用できます。
delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)
expect(ReservationMailer).to receive(:confirm_email)
.with('reservation')
.and_return(delivery)
もう少し追加するには、should_receiveを使用して呼び出しをスタブする場合は、他の場所で統合テストを行って、実際にメソッドを正しく呼び出していることを確認してください。
Should_receiveを使用して他の場所でテストされたメソッドを変更し、メソッド呼び出しが壊れた場合でもテストに合格することで、私は何度かビットを回ってきました。
Should_receiveを使用するよりも結果をテストしたい場合、shouldaには次のように機能するNiceマッチャーがあります。
it { should have_sent_email.with_subject(/is spam$/) }
Capybaraを Capybara Email と一緒に使用していて、 [email protected]
、この方法も使用できます。
email = open_email('[email protected]')
そして、あなたはこのようにそれをテストすることができます:
expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['[email protected]'])
試してみてください 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