Rails / Rspec:测试delayed_job邮件

时间:2011-06-15 02:22:29

标签: ruby-on-rails rspec 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

规格:

  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

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

任何赞赏的建议 - 欢呼

5 个答案:

答案 0 :(得分:48)

您还可以通过运行或关闭排队来测试作业的作用。

随时调整配置(即在before :each块中)。

Delayed::Worker.delay_jobs = false

或执行保存的工作

Delayed::Worker.new.work_off.should == [1, 0]

我一直在愉快地使用这种方法。首先,在RSpec中使用新的any_instance支持,您可以直接测试延迟方法效果。但是,我发现使用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)

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

答案 1 :(得分: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

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

  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

答案 2 :(得分:9)

您还可以遵循

的约定(来自Railscast 275
    ActionMailer::Base.deliveries.last.to.should == user.email

但是这样做:

    Delayed::Job.last.handler.should have_content(user.email)

答案 3 :(得分:0)

这个帖子有点老了,但是我在这里:

创建一个函数expect_jobs

def expect_jobs n, time = nil
  expect(Delayed::Job.count).to eq(n)
  Timecop.travel(time) unless time.nil?
  successes, failures = Delayed::Worker.new.work_off
  expect(successes).to eq(n)
  expect(failures).to eq(0)
  expect(Delayed::Job.count).to eq(0)
  Timecop.travel(Time.now) unless time.nil?
end

然后在检查回调是否完成其工作之前简单地调用它。例如:

it "sends a chapter to the admin user" do
  post :chapter_to_user, { chapter: @book.chapters.first}
  expect_jobs(1)
  SubscribeMailer.should have(1).delivery
  SubscribeMailer.deliveries.should have(1).attachment
end

这似乎对我有用,并允许我运行我的延迟工作我的方法。

答案 4 :(得分:0)

@zetetic我认为我们必须在这里传递block in change。

它应该是这样的:

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