Comments (21)
experiencing the same problem after upgrading from 2.2.0 to 2.2.1
test_helper.rb
# other requires
require "minitest-matchers"
require "email_spec"
# other requires
class ActiveSupport::TestCase
# other includes
include EmailSpec::Helpers
include EmailSpec::Matchers
# other includes
end
tests using reset_mailer
fail with the error:
NameError: undefined local variable or method `reset_mailer' for #<#<Class:0x00007f7aa5aeee90>:0x00007f7aa2d4eb20>
attempted to move includes to top/bottom of include list in class ActiveSupport::TestCase
as well as adding includes within the tests themselves but error still raised. reverting to 2.2.0 fixes the issue.
require "test_helper"
class SomeTest < ActiveSupport::TestCase
describe "a test" do
it "does a thing" do
reset_mailer
end
end
end
from email-spec.
Thanks, I can reproduce it. Looks like my projects have some other gems that also eager load actionmailer (what #219 corrected in this gem), hiding this problem for me.
I understand why it's happening, though I'm not sure what the fix is at the moment. Here's a summary incase anyone else has any ideas in the meantime.
At the point you require "email_spec/rspec"
, actionmailer is not yet loaded, so when the helpers are included into RSpec, this gem hasn't yet included the MailerDeliveries
module that defines reset_mailer
into the EmailSpec::Helpers
module.
Later, actionmailer is loaded, which now includes the EmailSpec::MailerDeliveries
module into the EmailSpec::Helpers
module.
However, Ruby doesn't seem to apply future includes into classes/modules the parent was previously included. Therefore, it's as if RSpec is frozen with the EmailSpec::Helpers
module WITHOUT EmailSpec::MailerDeliveries
, since that was the state of the module at the time it was included into RSpec.
This seems to be a quirk of Ruby, nothing specific to RSpec, as demonstrated by this script. Even though we've included B
into A
, which itself is included in Foo
, since B
was included in A
AFTER A
was included in Foo
, Foo
doesn't seem to treat B
as being an ancestor, hence the error when we call a method defined in B
. If you move the A.include(B)
line above the Foo
class definition, then it works.
I'll give some thought to what a fix could be. #219 corrected a real issue, so I don't think simply reverting it is the right fix. If actionmailer is loaded too early, then when you try to enable actionmailer configs in a new_framework_defaults
file of Rails, they don't actually take effect, as actionmailer was loaded before your initializer, and therefore it already copied all the configuration internally, and any other changes to configuration in an initializer via Rails.application.config
have no effect.
from email-spec.
fails too:
gem "email_spec", git: "https://github.com/email-spec/email-spec"
works:
gem "email_spec", "2.2.0"
from email-spec.
I can confirm this issue (Rails 5)
from email-spec.
Other than pinning to 2.2.0, does anyone have any workarounds, or any insight as to what has caused this and what might be the solution?
from email-spec.
@etagwerker and @cgunther may i ask you to check this issue?
from email-spec.
it looks like this commit 58f94e2 is the source of the problem
from email-spec.
What config.action_mailer.delivery_method
is set in your test environments? Mine is :test
and I've had no issues running with that across multiple projects.
There's a separate codepath for :activerecord
, so maybe the issue is there if you all coincidentally are using that delivery method? The test suite doesn't seem to cover that path, which could hide an issue. I'm not even seeing that Rails/ActionMailer supports :activerecord
out of the box, so is that coming from an external gem?
from email-spec.
What
config.action_mailer.delivery_method
is set in your test environments? Mine is:test
and I've had no issues running with that across multiple projects.
I have the delivery_method
as :test
on both my affected apps.
If there's anything I can do to help debug this, please let me know. One of my apps is an open-source prototype, and it's possible to use that to recreate the error - https://gitlab.com/gravitystorm/coppermill/ - if you release the pin in the Gemfile, run bundle update, then bundle exec rspec
will fail.
from email-spec.
However, Ruby doesn't seem to apply future includes into classes/modules the parent was previously included. Therefore, it's as if RSpec is frozen with the
EmailSpec::Helpers
module WITHOUTEmailSpec::MailerDeliveries
, since that was the state of the module at the time it was included into RSpec.This seems to be a quirk of Ruby, nothing specific to RSpec, as demonstrated by this script. Even though we've included
B
intoA
, which itself is included inFoo
, sinceB
was included inA
AFTERA
was included inFoo
,Foo
doesn't seem to treatB
as being an ancestor, hence the error when we call a method defined inB
. If you move theA.include(B)
line above theFoo
class definition, then it works.
This works so it's not completely stupid, but it does feel a bit yucky and I'm not sure why.
module A
end
module B
def bar
'bar'
end
end
class Foo
include A
def method_missing(method_name, *args, **kwargs, &block)
puts "method_missing(#{method_name.inspect}, #{args.inspect}, #{kwargs.inspect})"
if method_name == :bar
Foo.include A
send method_name, *args, **kwargs, &block
else
super
end
end
end
A.include(B)
puts Foo.new.bar
puts Foo.new.bar
# undefined method `bar' for #<Foo:0x00007fc43e0d4940> (NoMethodError)
method_missing(:bar, [], {})
bar
bar
11a12,21
>
> def method_missing(method_name, *args, **kwargs, &block)
> puts "method_missing(#{method_name.inspect}, #{args.inspect}, #{kwargs.inspect})"
> if method_name == :bar
> Foo.include A
> send method_name, *args, **kwargs, &block
> else
> super
> end
> end
15a26
> puts Foo.new.bar
from email-spec.
Unfortunately I don't think that would work, that was an oversimplified example, but thanks for the idea, seemed like it had some promise as I went down that path.
In our case, when method_missing
gets called, we'd have to include the appropriate deliveries module (and re-call the method), but wrapped in the ActiveSupport.on_load(:action_mailer)
block to avoid prematurely loading ActionMailer, which means method_missing
could return before that block gets called to re-call the method (ie. reset_mailer
).
Spending some more time on this, I'm still stumped. ActionMailer is lazily loaded in tests, so at the point reset_mailer
is called in the before
hook (using @gravitystorm's app) ActionMailer may not even be loaded yet (it could load later in the process of running the test). I'm starting to wonder if calling methods like reset_mailer
need to trigger loading ActionMailer itself, rather than waiting on Rails to load it, but still not simply upon requiring this library (as was the case prior to #219).
from email-spec.
I just started encountering this issue but I have 2.2.1
installed since September working.
I found that it started happening when I upgraded premailer-rails
from 1.11.1
to 1.12.0
. Hopefully that's a useful data point to someone.
from email-spec.
premailer-rails v1.12.0 fixed eagerloading ActionMailer (fphilipe/premailer-rails#260). Very similar in concept to what my PR introducing this issue here intended to do. Eager loading ActionMailer can cause headaches in the future, namely around trying to configure it via initializers.
In premailer-rails v1.11.1, ActionMailer was eagerly loaded, so email-spec could hook in properly, even with email-spec v2.2.1. With premailer-rails v1.12.0, ActionMailer is no longer eager loaded, and now email-spec seems to try hooking in too late.
I'm still rather stumped on the proper fix here. Before my PR, email-spec caused ActionMailer to be loaded too early, causing problems, and now ActionMailer is loaded too late, causing different problems.
from email-spec.
Did this ever get resolved? We are seeing the same intermittent error where a test gets run before ActionMailer is loaded, resulting in the error below:
NameError: undefined local variable or method `reset_mailer'
Would be great to have a recommended official fix.
from email-spec.
Hey! Any news with this issue? @etagwerker @bmabey @cgunther
from email-spec.
Related Issues (20)
- mail.html method useful? HOT 2
- Testing in isolation seems to fail HOT 1
- visit_in_email opens the wrong link
- Match have body text with special characters HOT 1
- Doesn't work anymore after upgrading Rails (ActionMailer::Base.deliveries is empty) HOT 3
- Email_spec causes rspec to fail (though not under Spring) HOT 5
- NameError: uninitialized constant RSpec::Expectations on current_email method
- NameError: uninitialized constant Delayed::DelayMail HOT 4
- Update to support mail gem 2.7 HOT 2
- `have_body_text` with URL now failing after upgrading `mail` gem from 2.6.6 to 2.7.0 HOT 3
- Incorrect parse of confirmation url generated by ahoy_email HOT 1
- Non compatible HTML entities encoding/decoding HOT 1
- New gem version HOT 2
- EmailSpec::CouldNotFindEmailError HOT 2
- checking for a mail in the queue with multiple properties HOT 1
- Add include_link matcher HOT 2
- I send my mail both via Pony and ActionMailer
- Getting uninitialized constant EmailSpec::Helpers HOT 5
- 2.2.1 gem released but master is 2.2.0 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from email-spec.