使用rspec codechool 5级测试进行测试3

时间:2014-04-05 20:49:47

标签: ruby-on-rails ruby rspec

以下是测试的基本问题:

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.***

型号:

# 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

邮件程序:

class ZombieMailer < ActionMailer::Base
  def tweet(zombie, tweet)
    mail(:from => 'admin@codeschool.com',
         :to => zombie.email,
         :subject => tweet.message)
  end
end

我一直在这方面蹦蹦跳跳,可以使用一些指针。以下是我现在一直在使用的内容:更新

describe Tweet do
  context 'after create' do
    let(:zombie) { Zombie.create(email: 'anything@example.org') }
    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

错误信息是:

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

任何rspec偷看都可以指出我在这里错过了什么?谢谢。

3 个答案:

答案 0 :(得分:1)

这个怎么样:

it 'calls "email_tweeter" on the tweet' do
  tweet.should_receive(:email_tweeter)
  tweet.save
end

答案 1 :(得分:0)

这样做

it 'calls "email_tweeter" on the tweet' do
  tweet.email_tweeter.should_receive(:zombie)
  tweet.save
end

答案 2 :(得分:0)

卸下:

  private :email_tweeter

您无法测试私有方法。

更新

事实上,您可以测试私有方法(使用不关心隐私的sendeval方法),但您不应该这样做,因为这些是实现的一部分而不是最终输出。在您的测试中,您应该保存一条新推文,检查是否已发送电子邮件。实现细节可以随时间变化,只要邮件正在发送,它就不应该影响测试。例如,您可以尝试:

it 'generates and sends an email' do
  tweet.save
  ActionMailer::Base.deliveries.last.message.should eq tweet.message
end