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

Luc*_*cas 0 rspec ruby-on-rails

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

我有一个名为的模型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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

谢谢!

wic*_*icz 5

你应该测试电话send_email.

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

Question没有线索如何发送电子邮件.它委托给QuestionMailer.因此检查上次发送的电子邮件,电子邮件队列等等是没有意义的.

我建议你花点时间观看Sandi Metz在RailsConf 2013上给出的精彩演示:测试的魔术技巧.幻灯片在这里.

最好!

更新:如何处理self.id

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

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

如果你真的想要/需要坚持self.id,你可以测试stubQuestion实例中的任何值.请记住,您是单元测试 #send_mail,因此id数据库的存根或生成值是否真的无关紧要.您点击数据库的次数越少,测试运行的速度就越快.