8

RSpec統合テストを作成しました。test.logによると、メールを送信したことがわかりますが、ActionMailer :: Base.deliveriesを使用してメールにアクセスしようとすると、常に空であることが示されます。

私は他の同様の質問を読み、すべてを試しました。私は困惑しています。

Capybara/RSpecを使用したコードは次のとおりです。

it "should notify owner" do

  puts "Delivery method: #{ActionMailer::Base.delivery_method.inspect}"
  # This returns: ":test", which is correct

  # Get other guests to do the review
  @review = Review.last
  share_link = "http://#{@account.subdomain}.cozimo.local:#{Capybara.server_port}/review/#{@review.slug}"

  visit(share_link)

  fill_in "email", :with => @user1.email
  fill_in "password", :with => "foobar"

  click_button "Start Review"

  # Add a comment
  click_on "ice-global-note-button"
  find(:css, "#ice-global-note-panel > textarea.ui-corner-all").set "Foo"
  click_on "ice-global-note-submit-button"

  # Test is failing here. WTF? The array should not be empty
  ActionMailer::Base.deliveries.empty?.should be_false

  # Check that a notification email was sent to the owner
  open_email(@owner.email)
  current_email.should have_content "Hi #{@owner.first_name}"

end

上記のように、config.action_mailer.delivery_method =:test

test.logでは、メールが実際に送信されていることが示されています。

Sent mail to somebody1@example.com (62ms)
Date: Tue, 29 Jan 2013 13:53:48 -0500
From: Review Studio <support@cozimo.com>
To: somebody1@example.com
Message-ID: <51081abcd9fbf_5bd23fef87b264a08066@Leonards-MacBook-Pro.local.mail>
Subject: Notes added for Test
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Hi Bruce,

Just letting you know that you have new notes added to the review:

  Project: Test
  Description: Test description
  URL: http://ballistiq.cozimo.local:3000/review/625682740

Thanks,

Review Studio
Completed 200 OK in 170ms (Views: 0.2ms | ActiveRecord: 4.3ms)
4

6 に答える 6

8

これは、Capybara と Selenium を使用した統合テストです。したがって、アプリケーションがメールを送信したことを確認する前に、アプリケーションが実際にメールを送信するのを待つ必要があります。

注 - これで問題は解決しますが、一般的に悪い習慣です

a を追加しsleep 1て、rspec にメール送信イベントのトリガー後に待機するように指示します。その後、ActionMailer::Base.deliveries 配列をチェックして再開し、渡されます。

前述のように、これはテストの速度を低下させるため、一般的に悪い習慣です。

より良い方法

統合テストは、メールが送信されることをまったくテストすべきではありません。テストは、テスト対象のクラスの明確な責任に分割する必要があります。したがって、別のクラス (コントローラーまたはリソース テスト) で送信されるメールのみをテストするように、テストを別の方法で構成します。メールメソッドの呼び出しが実際に行われたことを確認するために期待値を使用することもできますが、それでもタイミングの問題が発生する可能性があります。

于 2013-01-29T19:37:53.120 に答える
5

スペックでスリープや時間のかかる方法を使用しないでください。スペックが遅くなるだけではありません。

メーラーで期待値を使用してみてください。テストの開始時に、次のようなものを追加してください。

mail = mock(mail)
mail.should_receive(:deliver)
YourMailer.should_receive(:your_method).once.and_return(mail)

そうすれば、待つ必要はなく、実際にテストする必要があるもの(コードがメールを作成して配信する)をテストし、メーラーコード(メールオブジェクトでdeliverを呼び出すだけで、実際の配信は仕事です)ではありません。 ActionMailerテストの一部であり、アプリケーションでは何の関係もありません。これらのメソッドの呼び出しが機能することを信頼する必要があります)

于 2013-01-30T00:55:22.053 に答える
0

sleep()一般的に、テストでは避けたいと思います。Capybara との統合テストを行う場合は、待機するメソッドを使用するだけです。

たとえば、このテストは断続的に失敗します (valid_step_7メールを送信します)。

it "should get past step 7 and send an email" do
  valid_step_5_no_children
  valid_step_7

  expect(ActionMailer::Base.deliveries.count).to eq(1)
  expect(page).to have_content "I AM JOHN DOE"
end

これは、最後のステップ (valid_step_7) を終了し、即座に 'ActionMailer::Base.deliveries.count' をチェックして 1 に等しいかどうかを確認しているためですが、必ずしも deliverys 配列 (からとにかく私のデバッグ)。

最初に次のページのコンテンツをチェックするためにテストを反転させてから、ランダムな失敗はありませんでしたActionMailer::Base.deliveries

it "should get past step 7 and send an email" do
  valid_step_5_no_children
  valid_step_7

  expect(page).to have_content "I AM JOHN DOE"
  expect(ActionMailer::Base.deliveries.count).to eq(1)
end

うまくsleep(1)いくと思いますが、必要のないときに1秒のスリープを強制していると思います。

于 2016-06-22T04:23:22.993 に答える
0

javascript POST のスリープの代わりに、この wait_for_ajax ヘルパーを使用することもできます。ajax が終了するまでカピバラを待たせます。

module WaitForAjax
  def wait_for_ajax
   Timeout.timeout(Capybara.default_wait_time) do
    loop until finished_all_ajax_requests?
   end
  end

  def finished_all_ajax_requests?
   page.evaluate_script('jQuery.active').zero?
  end
end

RSpec.configure do |config|
  config.include WaitForAjax, type: :feature
end

ソース: https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara

于 2015-03-18T22:38:23.573 に答える