我应该如何测试" after_create"使用rspec发送电子邮件的回调

时间:2014-07-28 18:49:23

标签: ruby-on-rails rspec

我的问题是如何规定回调以正确的方式发送电子邮件。

我有一个名为Question的模型。创建question后,我有一个回调after_create来发送电子邮件。

我想创建一个rpsec来测试这个方法。但是,我已经为每个邮件程序提供了规范,用于验证电子邮件是否实际发送以及收件人。

所以,我想知道在after_create内是否应该测试send_mail方法的调用或检查上次发送的电子邮件是否存在?因为,就像我说的那样,电子邮件本身的测试是在邮件的spec/mailers/question_mailer_spec.rb

的规范中

型号:

class Question < ActiveRecord::Base

after_create :send_email

def send_email
   QuestionMailer.send_email(:questioned, self.id)
end

Rspec的:

describe "#send_email" do
  it "should sends email after create" do
     expect(QuestionMailer).to receive(:send_email).with(:questioned, **question.id**) 
     question = create(:question)

  end
end

谢谢!

1 个答案:

答案 0 :(得分:5)

您应测试对send_email的调用。

您希望断言实现的行为,而不是实现本身。在这种情况下,邮件从Question发送给其协作者QuestionMailer。请记住,测试界面,而不是实现细节。

Question无法确定电子邮件的发送方式。它委托给QuestionMailer。因此,检查上次发送的电子邮件,电子邮件队列等等是没有意义的。

我建议你花点时间观看Sandi Metz在2013年RailsConf上发表的精彩演讲:The Magic Tricks of Testing。幻灯片是here

最佳!

更新:如何处理self.id

我认为如果你通过self而不是self.id会更好。除了解决你的问题,它:

  • 让您的代码更具表现力;
  • 避免使用原始值(整数);
  • 可能会阻止您的生产代码中至少再读取一个数据库。

如果您确实需要/需要坚持self.id,您可以stub正在测试的Question实例中的任何值。请注意,您已经单元测试 #send_mail,因此,id的值是由数据库存根或生成的,这并不重要。并且您对数据库的攻击越少,测试运行的速度就越快。