1
votes

Rails 4.1.4 and Rspec 3

I'm doing a VERY basic email test with Rspec. If I call the mailer from rails console, it works perfectly. If I call it from the mailer spec I get:

wrong number of arguments (0 for 1..2)

The mailer is very basic:

  def create_team_invite(org, email)
    @organization = org
    mail(:to=>email, :subject=>'Test Subject')
  end

The Test is pretty basic too:

it 'can send out emails to invite others to create teams' do
  UserMailer.create_team_invite(@org, '[email protected]').deliver
  expect(ActionMailer::Base.deliveries.count).to eq 1
  mail = ActionMailer::Base.deliveries.first
  expect(mail.subject).to eq 'Test Subject'
  expect(mail.from).to eq '[email protected]'
end

Its failing in the "mail(:to..." line in the mailer. Seems like maybe its some configuration issue in my environment, but I have Test setup exactly the same as Dev, using SMTP and sending it to a Mailcatcher port. I caught the exception and looked at the Backtrace, but don't see anything unusual...

Anyone seen this before?

Update: providing additional info that was requested.

My test.rb, minus comments:

Rails.application.configure do
  config.cache_classes = true
  config.eager_load = false
  config.serve_static_assets  = true
  config.static_cache_control = 'public, max-age=3600'
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false
  config.action_dispatch.show_exceptions = false
  config.action_controller.allow_forgery_protection = false
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.perform_deliveries = true
  config.active_support.deprecation = :stderr
  config.action_mailer.default_url_options = { :host => 'lvh.me:3000', :only_path=>false }
end

The entire rspec failure is:

UserMailer

Team Joining Email can send out emails to invite others to create teams (FAILED - 1)

Failures:

  1) UserMailer Team Joining Email can send out emails to invite others to create teams
     Failure/Error: UserMailer.create_team_invite(@team, '[email protected]').deliver
     ArgumentError:
       wrong number of arguments (0 for 1..2)
     # ./app/mailers/user_mailer.rb:11:in `create_team_invite'
     # ./spec/mailers/user_mailer_spec.rb:36:in `block (3 levels) in <top (required)>'

Finished in 0.25858 seconds (files took 29 minutes 48 seconds to load)
1 example, 1 failure

The way I configure my email is via an initializer that loads an email.yml file from my config, per environment. Exact same process used by both test and dev, with the same settings. (Again, I'm sending to Mailcatcher, instead of just to mail_delivery :test)

Update 2

I have narrowed it down to the Mailer missing the "request" object. If I dig through where the error is occurring (AbstractController rendering.rb, line 109) it tries to reference the request object:

if defined?(request) && request && request.variant.present?

This is calling over to Rack test.rb line 121:

  def request(uri, env = {}, &block)
    env = env_for(uri, env)
    process_request(uri, env, &block)
  end

So its like the Rack Test.rb class is being seen as the request method in that abstractcontroller... but I dont know how, or why, or why this is happening in this particular project...

1
share your environments/test.rb please. Also, can we see the entire test failure...Anthony
I shared them above - dont suppose you have any ideas?Dave Sanders
I deleted my answer. I thought that it was a URI issue in the template, but it appears its not. I was just hiding the error so I thought it was working. Still getting the same error and tracing it in the gems isn't showing me anything useful. Good times.Dave Sanders
can you try changing the #delivery_method to: config.action_mailer.delivery_method = :test ?Anthony
also your test is failing on UserMailer.create_team_invite(@team, '[email protected]').deliver but the test you gave us shows you're sending an @org to it. Do we have the right info here?Anthony

1 Answers

0
votes

I get this same exact error, and it seems that it's trying to call rack-test request code, when I'm just trying to test a mailer object. So what I did is just not include all the stuff that I put in the spec_helper for the mailer spec. That fixed the problem for me.

# require 'spec_helper' -> I removed this line, 
# and manually require the files that's needed to just test the mailer object: 
require 'rubygems'
require './config/environment'
require './app/mailers/your_mailer'

Note: I'm just doing a rack project using action_mailer, no rails stuff. So your solution will be different, but you get the idea.

Update:

After doing some more troubleshooting. I found this problem in my spec_helper.rb file

RSpec.configure do |config|
  config.include include RackSpecHelper # notice the double include
  ...
end

# where RackSpecHelper is a custom module
module RackSpecHelper
  include Rack::Test::Methods
  # a bunch of other helper methods
end

Notice the double include on this line

config.include include RackSpecHelper

At first I tried just removing the line and my mailer test is running just fine. Suspicious with the double include, I remove the include so it's just like this

config.include RackSpecHelper

Now my mailer test runs just fine without having to do manual require like I posted earlier above (and it can run together with the other test that uses rack test stuff).

The double include is basically doing

config.include(include(RackSpecHelper))

which include the RackSpecHelper in the configure block, which loads all the methods in the top level namespace! (very bad thing). It works, but that means all the methods from Rack::Test::Methods are in the global namespace.

So I'm guessing in your case, you might have a line in the spec_helper that include Rack::Test::Methods in the global namespace like this

include Rack::Test::Methods

remove it and instead put it in the RSpec config like this

RSpec.configure do |config|
  config.include RackSpecHelper
end