0
votes

Here is the base question for the test:

We've verified that the ZombieMailer is being called with the correct parameters, but not that deliver is being called on the resulting mail object. Complete the new example by stubbing out the ZombieMailer.tweet method and having it return mail. Then make sure that the deliver method is called on the mail object.

Unfortunately I can not alter the models, question, or mailer.

Models:

# tweet.rb
class Tweet < ActiveRecord::Base
  belongs_to :zombie
  validates :message, presence: true
  attr_accessible :message

  after_create :email_tweeter

  def email_tweeter
    ZombieMailer.tweet(zombie, self).deliver
  end
  private :email_tweeter
end

# zombie.rb
class Zombie < ActiveRecord::Base
  has_many :tweets
  validates :email, presence: true
  attr_accessible :email
end

Mailer:

class ZombieMailer < ActionMailer::Base
  def tweet(zombie, tweet)
    mail(:from => '[email protected]',
         :to => zombie.email,
         :subject => tweet.message)
  end
end

The test starts out as:

describe Tweet do
  context 'after create' do
    let(:zombie) { Zombie.create(email: '[email protected]') }
    let(:tweet) { zombie.tweets.new(message: 'Arrrrgggghhhh') }
    let(:mail) { stub(:mail, deliver: true) }

    it 'calls "tweet" on the ZombieMailer' do
      ZombieMailer.should_receive(:tweet).with(zombie, tweet).and_return(mail)
      tweet.save
    end

    it 'calls "deliver" on the mail object' do
      pending
    end
  end
end

I keep bouncing around on this and could use a few pointers. Here is what I have been working with now. Thoughts? Pointers?

My current attempt: UPDATED

describe Tweet do
  context 'after create' do
    let(:zombie) { Zombie.create(email: '[email protected]') }
    let(:tweet) { zombie.tweets.new(message: 'Arrrrgggghhhh') }
    let(:mail) { stub(:mail, deliver: true) }

    it 'calls "tweet" on the ZombieMailer' do
      ZombieMailer.should_receive(:tweet).with(zombie, tweet).and_return(mail)
      tweet.save
    end

    it 'calls "deliver" on the mail object' do
      ZombieMailer.stub(:tweet).and_return(mail)
      ZombieMailer.should_receive(:tweet).with(zombie, tweet).and_return(mail)
      mail.should_receive(:deliver)
    end
  end
end

And the error message is:

Failures:

1) Tweet after create calls "deliver" on the mail object
Failure/Error:       ZombieMailer.should_receive(:tweet).with(zombie, tweet).and_return(mail)
NameError:
undefined local variable or method `      ZombieMailer' for #<RSpec::Core::ExampleGroup::Nested_44::Nested_1:0x00000005ade670>
# zombie_spec.rb:14:in `block (3 levels) '

Finished in 0.37774 seconds
2 examples, 1 failure

Failed examples:

rspec zombie_spec.rb:12 # Tweet after create calls "deliver" on the mail object

Any rspec peeps out there can point me in the right direction as to what I am missing here? Thank you.

1

1 Answers

0
votes
describe Tweet do
  context 'after create' do
    let(:zombie) { Zombie.create(email: '[email protected]') }
    let(:tweet) { zombie.tweets.new(message: 'Arrrrgggghhhh') }
    let(:mail) { stub(:mail, deliver: true) }

    it 'calls "tweet" on the ZombieMailer' do
      ZombieMailer.should_receive(:tweet).with(zombie, tweet).and_return(mail)
      tweet.save
    end

    # Updated
    it 'calls "deliver" on the mail object' do
     ZombieMailer.stub(:tweet).and_return(mail)
     mail.should_receive(:deliver).and_return(true)
     tweet.save
    end
  end
end

I would try something like the above. The main issue I see in the spec is that the method expected is not being called.

I haven't tested this though.