Rspec-rails: have_enqueued_email not working

Created on 10 Mar 2020  路  14Comments  路  Source: rspec/rspec-rails

Subject of the issue

I'm trying to use the new have_enqueued_email matcher in one of my specs, but RSpec keeps telling me the format is incorrect

Your environment

  • Ruby version: 2.6.5
  • rspec-expectations version: 3.9.0

Steps to reproduce

  • Write code to schedule a Mailer with .deliver_now
  • Setup RSpec to support ActiveJob
  • write the following spec : expect { post(:email_quote, params: quote_params) }.to have_enqueued_email(MyMailer, :quote)

Expected behavior

Test to pass

Actual behavior

Test fails with the error :

You must pass an argument rather than a block to `expect` to use the provided matcher (have enqueued email QuoteMailer, :quote), or the matcher must implement `supports_block_expectations?`.

The test:

describe "#quote_email" do
    subject(:quote_email) { post(:email_quote, params: quote_params) }
    let(:email) { "[email protected]" }
    let(:quote_params) { { item: item_params, email: email } }
    let(:item_params) do
      { variant_id: variant.id, quantity: 100, decoration_id: decoration.id, number_of_colors: 1, is_sample: false }
    end

    before { ActiveJob::Base.queue_adapter = :test }

    it "properly schedules the Mailer for sending the email" do
      expect { subject }.to have_enqueued_email(QuoteMailer, :quote)
    end
  end

The code for invoking in the controller:

def email_quote
    item = params.require(:item).permit!.to_h
    email = params.require(:email)

    QuoteMailer.quote(item, email).deliver_later
    render json: true
  end

Most helpful comment

I've release 3.9.1 as a fix for this, it seems silly not to.

All 14 comments

That's strange.
Can you drop a breakpoint before this line:

expect { subject }.to have_enqueued_email(QuoteMailer, :quote)

and check the source of have_enqueued_email? In case you use Pry:

> $ have_enqueued_mail

it should be:

      def have_enqueued_mail(mailer_class = nil, mail_method_name = nil)
        HaveEnqueuedMail.new(mailer_class, mail_method_name)
      end

:have_enqueued_email is an alias of have_enqueued_mail.

Can you call have_enqueued_email(QuoteMailer, :quote).supports_block_expectations?, is this method defined, does it evaluate to true?

I'm not familiar with Pry, so I tried the command you told to use:

> have_enqueued_mail
=> #<RSpec::Matchers::BuiltIn::Has:0x00007f8e87a4e558 @args=[], @block=nil, @method_name=:have_enqueued_mail>
0> have_enqueued_email(QuoteMailer, :quote).supports_block_expectations?
=> false
> have_enqueued_mail
=> #<RSpec::Matchers::BuiltIn::Has:0x00007f8e87a4e558 @args=[], @block=nil, @method_name=:have_enqueued_mail>

This is your problem you're not using the right matcher, thats the has_<n> matcher which is not the same. Are you using rspec-rails from Github or from 4.0.0.beta3 or 4.0.0.beta4?

normal gem installation

group :test do
  gem "factory_bot_rails", require: false
  gem "rails-controller-testing"
  gem "rspec-collection_matchers"
  gem "rspec-nc"
  gem "rspec-rails"
  gem "rspec_junit_formatter"
  gem "simplecov", require: false
  gem "timecop"
end

Ok, you need to use 4.0.0.beta3 or 4.0.0.beta4 to use this matcher. Rubygems will not give you beta's unless you ask for them, change gem "rspec-rails" for gem "rspec-rails", "4.0.0.beta4"

Also, I suggest moving rspec-rails to :development, :test group as doc suggests.

~I'm not sure thats relevant @pirj, the matcher didn't exist before 4.0.0 you'd need a beta anyway.~
Edit, I was wrong.

Thanks for the clarifications. I think I just got lost in all the docs I was reading about this matcher, that I missed the point this isn't released yet officially.

this is what threw me off : https://www.rubydoc.info/gems/rspec-rails/RSpec%2FRails%2FMatchers:have_enqueued_mail

As the version on top says 3.9.0

It is officially released, we just haven't published as 4.0.0 final yet.

My apologies, it seems it was shipped in 3.9.0 I mis-remembered and then mis-read the change log :joy: , yes there is a bug with the require, you can work around it by requiring it manually.

I've release 3.9.1 as a fix for this, it seems silly not to.

Was this page helpful?
0 / 5 - 0 ratings