Reputation: 3558
Here is the base question for the test:
Update the spec so that whenever a tweet is created, we verify that email_tweeter is called on the tweet object. ***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
I keep bouncing around on this and could use a few pointers. Here is what I have been working with now: UPDATED
describe Tweet do
context 'after create' do
let(:zombie) { Zombie.create(email: '[email protected]') }
let(:tweet) { zombie.tweets.new(message: 'Arrrrgggghhhh') }
it 'calls "email_tweeter" on the tweet' do
tweet.email_tweeter.should_receive(:zombie)
tweet.save
end
end
end
And the error message is:
Failures:
1) Tweet after create calls "email_tweeter" on the tweet
Failure/Error: tweet.email_tweeter.should_receive(:zombie)
NoMethodError:
private method `email_tweeter' called for #<Tweet:0x000000062efb48>
# zombie_spec.rb:7:in `block (3 levels) '
Finished in 0.26328 seconds
1 example, 1 failure
Failed examples:
rspec zombie_spec.rb:6 # Tweet after create calls "email_tweeter" on the tweet
Any rspec peeps out there can point me in the right direction as to what I am missing here? Thank you.
Upvotes: 0
Views: 163
Reputation: 53018
How about this:
it 'calls "email_tweeter" on the tweet' do
tweet.should_receive(:email_tweeter)
tweet.save
end
Upvotes: 1
Reputation: 44675
Remove:
private :email_tweeter
You can't test private methods.
Update:
In fact you can test private methods (with send
or eval
methods which do not care about privacy), but you shouldn't, as those are part of implementation not the final output. In your tests you should rather save a new tweet an check that email has been sent. implementation details can change with time, it shouldn't affect tests as long as the mail is being send. You can for example try:
it 'generates and sends an email' do
tweet.save
ActionMailer::Base.deliveries.last.message.should eq tweet.message
end
Upvotes: 0
Reputation: 8122
do this
it 'calls "email_tweeter" on the tweet' do
tweet.email_tweeter.should_receive(:zombie)
tweet.save
end
Upvotes: 0