Hung
Hung

Reputation: 519

Can not test mailer action called in rspec rails

In mailer of rails, as I know all method will be class method. But I can not test my mailer method called:

user_mailer_spec.rb:

it "should call send_notifition method" do
        @user = FactoryGirl.build(:user)
        notify_email = double(:send_notifition)
        expect(UsersMailer.new).to receive(:notify_email).with(@user)
        @user.save
end

user_mailer.rb:

def notify(user)
     mail to: user.email, subject: "Example"
end

user.rb:

after_commit :send_notifition

private

def send_notifition
    UsersMailer.notify(self)
end

The above codes will not pass but when I change notifition to self.notifition, it pass:

def self.notify(user)
     mail to: user.email, subject: "Example"
end

Upvotes: 0

Views: 1805

Answers (2)

Hung
Hung

Reputation: 519

Solved: Thank you @Clemens Kofler for supporting. I have many mistaking in my code:

  • First: No need to install gem "email_spec", and change user.rb file

from

after_commit :send_notifition

private

def send_notifition
    UsersMailer.notify(self)
end

to

after_commit :send_notifition

private

def send_notifition
    UsersMailer.notify(self).deliver
end
  • Second: Change user_mailer_spec.rb file

from

it "should call send_notifition method" do
        @user = FactoryGirl.build(:user)
        expect(@user).to receive(:send_notifition)
        notify_email = double(:send_notifition)
        expect(UsersMailer.new).to receive(:notify_email).with(@user)
        @user.save
  end

to

it "should call send_notifition_mail_if_created_new_hospital method" do
        @user = FactoryGirl.build(:user)
        # I don't know why "expect(@user).to receive(:send_notifition)" not passed here
        mail = double(:mail)
        expect(UsersMailer).to receive(:notify_email).with(@user).and_return(mail)
        allow(mail).to receive(:deliver)
        @user.save
    end
  • Finally: config mailer in config/environments/test.rb for test environment can use mailer (because spec run in test env)

Upvotes: 1

Clemens Kofler
Clemens Kofler

Reputation: 1968

First of all, I'd like to point you to an awesome gem for testing emails: https://github.com/email-spec/email-spec.

I think the problem is that you're asserting on UsersMailer.new, thus putting a mock on a different instance than the one then being instantiated by the User model. I generally test emails like this without any issues:

it "should call send_notifition method" do
  @user = FactoryGirl.build(:user)

  mail = double(:mail)
  expect(UsersMailer).to receive(:notify_email).with(@user).and_return(mail)
  expect(mail).to receive(:deliver_later) # or deliver_now, if you don't use a background queue

  @user.save
end

Note how I'm doing expect(UsersMailer) instead of expect(UsersMailer.new) and also take not that I'm asserting that the email is actually delivered (I think a deliver statement is missing in your code).

Hope that helps.

Upvotes: 4

Related Questions