Rails/Rspec:测试delayed_job邮件

Pla*_*Ton 24 rspec ruby-on-rails delayed-job

只是想知道如何测试动作邮件请求实际上是发送到rspec中的delayed_job que.

我原以为它很简单,但我的delayed_job队列似乎没有增加.代码如下:

控制器:

  def create
    @contact = Contact.new(params[:contact])
      if @contact.save
        contactmailer = ContactMailer
        contactmailer.delay.contact_message(@contact)
        redirect_to(contacts_url)
      else
        render :action => "new"
      end
Run Code Online (Sandbox Code Playgroud)

规格:

  it "queues mail when a contact is created" do
    expectedcount = Delayed::Job.count + 1
    Contact.stub(:new).with(mock_contact()) { mock_contact(:save => true) }
    post :create, :contact => mock_contact
    expectedcount.should eq(Delayed::Job.count)
  end
Run Code Online (Sandbox Code Playgroud)

在调用控制器之前和之后,Delayed :: Job.count都返回0.我已经尝试从控制器中取出条件,但我仍然无法使延迟的作业数增加.

任何建议赞赏 - 欢呼

Joh*_*gan 48

您还可以通过运行或关闭排队来测试作业将执行的操作.

随时调整配置(即在一个before :each块中).

Delayed::Worker.delay_jobs = false
Run Code Online (Sandbox Code Playgroud)

或执行您保存的工作

Delayed::Worker.new.work_off.should == [1, 0]
Run Code Online (Sandbox Code Playgroud)

我一直在愉快地使用这种方法.首先,使用any_instanceRSpec中的新支持,您可以直接测试延迟方法效果.但是,我发现测试速度work_off.

我现在通常做的是:

mock_delay = double('mock_delay').as_null_object
MyClass.any_instance.stub(:delay).and_return(mock_delay)
mock_delay.should_receive(:my_delayed_method)
Run Code Online (Sandbox Code Playgroud)

然后我有一个单独的规格my_delayed_method.这要快得多,而且可能是更好的单元测试实践 - 特别是对于控制器.虽然如果您正在执行请求规范或其他集成级别的规范,那么您可能仍然想要使用work_off.


zet*_*tic 16

我认为你的模拟对象在某种程度上引入了一个错误 - 如果没有看到mock_contact方法的定义,很难确切地说出错误.

无论如何,你可以尝试这些方面:

  it "queues mail when a contact is created" do
    Contact.stub(:new) { mock_model(Contact,:save => true) }
    Delayed::Job.count.should == 0
    post :create, {}
    Delayed::Job.count.should == 1
  end
Run Code Online (Sandbox Code Playgroud)

或更性感的版本(警告:我总是以不性感的方式做到这一点):

  it "queues mail when a contact is created" do
    Contact.stub(:new) { mock_model(Contact,:save => true) }
    expect {
      post :create, {}
    }.to change(Delayed::Job.count).by(1)
  end
Run Code Online (Sandbox Code Playgroud)


ajb*_*aus 9

你也可以遵循约定(来自Railscast 275)

    ActionMailer::Base.deliveries.last.to.should == user.email
Run Code Online (Sandbox Code Playgroud)

但是这样做:

    Delayed::Job.last.handler.should have_content(user.email)
Run Code Online (Sandbox Code Playgroud)