-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible regression 4.0.0.beta4 to 4.0.0.rc1: List of ActionMailer deliveries is not cleared between specs #2290
Comments
At the moment I see nothing relevant here v4.0.0.beta3...v4.0.0.rc1 Did you try
Yes please |
Yes, I tried v4.0.0.beta3 and that works fine. |
Have you tried |
Ah, I'm sorry, I wasn't aware of a beta 4. |
I couldn't find anything suspicious. Can you help us by bisecting the failure to a specific commit @cunknown ? |
I don't understand why I have this result. But this was my approach:
I did this procedure twice because I could not understand why removing What am I doing wrong? |
Several of those seem bad :/, if you have the time to investigate further maybe step through the commits in your gemfile manually |
I have isolated the issue into an example app: When bundling with '4.0.0.beta4', the problem_spec.rb will pass. When bundling with
|
With your repo it seems the error is because of
|
Looks like that besides the added test, the removal of the following results in reusing the ActionMailer::Base instance between tests?
|
This reverts commit 3e4c770. Do not remove ::ActionDispatch::IntegrationTest::Behavior because this lead to unwanted behavior like uncleaned queue for ActionMailer::Base.deliveries between tests. As suggested in rails/rails#37270 there is many other way to implement this. At the moment this line seems to be enough for our case. Fix: #2290 Related: - rails/rails#37270
I am able to still have green system specs and green repo project test suite with this patch: diff --git a/lib/rspec/rails/example/system_example_group.rb b/lib/rspec/rails/example/system_example_group.rb
index 691b1f0c..e72a6f76 100644
--- a/lib/rspec/rails/example/system_example_group.rb
+++ b/lib/rspec/rails/example/system_example_group.rb
@@ -75,6 +75,7 @@ module RSpec
original_after_teardown =
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:after_teardown)
+ other.include ::ActionDispatch::IntegrationTest::Behavior
other.include ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown
other.include ::ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
other.include BlowAwayTeardownHooks
@@ -102,6 +103,9 @@ module RSpec
before do
@routes = ::Rails.application.routes
+ # (ActiveJob::Base.descendants << ActiveJob::Base).each(&:disable_test_adapter)
+ # or
+ ActiveJob::Base.disable_test_adapter
end Run after My question is: Do we want to set When I see shared fixes [1], [2], [3] it seems that we should revert 3e4c770 and maybe disable test adapter ourself. What do you think @JonRowe and @pirj ? Proposal: #2292 Side note from the doc: https://github.com/rails/rails/blob/f265e0ddb1139a91635b7905aae1be76b22c6db1/guides/source/testing.md#L1667-L1670 |
We don't want to disable the test adapter, we just need to not share the deliveries between tests. IIRC the reason why it got removed was it preventing setting other adapters.. So maybe we have to reset the deliveries between tests? |
I think if we do this we will have deal to clean queue for other part of rails code. I think removing I will dig deeper to see what people do. |
On mailboxer gem they are doing this since 2014: # Rspec only clears out ActionMailer::Base#deliveries for mailers specs
config.after(:each, type: :integration){ ActionMailer::Base.deliveries.clear } |
Another proposal could be: --- a/lib/rspec/rails/example/system_example_group.rb
+++ b/lib/rspec/rails/example/system_example_group.rb
@@ -101,6 +101,7 @@ module RSpec
end
before do
+ ActionMailer::Base.deliveries.clear But system specs are probably not enough. |
Might be quite radical, but WDYT of: if RSpec::Rails::FeatureCheck.has_active_job?
before { ActionMailer::Base.deliveries.clear }
end not only for Side question: does having ActiveJob in place automatically mean we have ActionMailer? We kind of assume that when requiring |
I think we just check if we have deliveries, if so clear it each test. |
Another draft proposal. --- a/lib/rspec/rails/example/rails_example_group.rb
+++ b/lib/rspec/rails/example/rails_example_group.rb
@@ -12,6 +12,14 @@ module RSpec
include RSpec::Rails::MinitestLifecycleAdapter
include RSpec::Rails::MinitestAssertionAdapter
include RSpec::Rails::FixtureSupport
+
+ included do
+ after do
+ if defined?(ActionMailer) && ActionMailer::Base.deliveries.any?
+ ActionMailer::Base.deliveries.clear
+ end
+ end
+ end
end
end
end
# spec/services/mailer_service_spec.rb
# frozen_string_literal: true
require 'system_helper'
RSpec.describe MailerService do
describe '#call' do
context 'one email' do
it do
MailerService.call(to: '[email protected]')
expect(ActionMailer::Base.deliveries.map(&:to).flatten.sort).to eq(['[email protected]'])
end
end
context 'other email' do
it do
MailerService.call(to: '[email protected]')
expect(ActionMailer::Base.deliveries.map(&:to).flatten.sort).to eq(['[email protected]'])
end
end
end
end One of the example will fail because it is not cleaned. Is there a better place to put it? I dig into the code but didn't find something like a prepend to spec_helper. You load |
# lib/rspec/rails/configuration.rb:138
if RSpec::Rails::FeatureCheck.has_action_mailer?
config.include RSpec::Rails::MailerExampleGroup, type: :mailer
+ config.after { ActionMailer::Base.deliveries.clear }
end |
That's perfect. Thanks Jon. I will write the test tomorrow. |
What Ruby, Rails and RSpec versions are you using?
Ruby version: 2.7.0
Rails version: 6.0.2
RSpec version: 4.0.0.rc1
The following is included for these mailer tests:
RSpec.configure do |config|
config.include ActionMailer::TestHelper
end
Observed behaviour
When running specs, we check the to adresses that are set for the ActionMailer::Base.deliveries, like this:
This works for version
4.0.0.beta3
and4.0.0.beta4
, but for4.0.0.rc1
, this will break.It seems that the deliveries array is not cleared between specs. The list of email addresses that are stored in the TO of the mailer, will get larger after each spec. Therefore, running each spec seperately works, but when the fourth or fifth spec is ran, the list of adresses is way bigger than expected:
Expected behaviour
The ActionMailer instance is reset between each spec and the TO, CC and BCC attributes of ActionMailer::Base.deliveries should be cleared between each spec.
Can you provide an example app?
I have isolated the issue into an example app:
https://github.com/CUnknown/rspec-rails-bug-example
The text was updated successfully, but these errors were encountered: