【问题标题】:Setting expectation on resque .perform method. Task is enqueued in a Callback对 resque .perform 方法设定期望。任务在回调中排队
【发布时间】:2012-08-27 21:40:39
【问题描述】:

所以根据我的理解,我相信你这样做

Resque.inline = Rails.env.test?

您的 resque 任务将同步运行。我正在编写一个关于在 after_commit 回调期间排队的 resque 任务的测试。

after_commit :enqueue_several_jobs

#class PingsEvent < ActiveRecord::Base
...
   def enqueue_several_jobs
      Resque.enqueue(PingFacebook, self.id)
      Resque.enqueue(PingTwitter, self.id)
      Resque.enqueue(PingPinterest, self.id)
   end

在我的 Resque 任务类的 .perform 方法中,我正在执行 Rails.logger.info 并且在我的测试中,我正在执行类似的操作

..
Rails.logger.should_receive(:info).with("PingFacebook sent with id #{dummy_event.id}")
PingsEvent.create(params)

我对@9​​87654328@ 和PingPinterest 进行了相同的测试。

我的第二个和第三个期望都失败了,因为似乎测试实际上在所有 resque 作业运行之前完成。只有第一个测试真正通过。 RSpec 然后抛出一个MockExpectationError 告诉我Rails.logger 没有收到其他两个测试的.info。有人有过这方面的经验吗?

编辑

有人提到should_receive 的行为类似于mock,而我应该改为.exactly(n).times。很抱歉没有早点说清楚,但我对不同的it 块有我的期望,我认为一个it 块中的should_receive 不会在下一个it 块中模拟它?如果我错了,请告诉我。

【问题讨论】:

  • 这对你有用吗?

标签: ruby-on-rails rspec resque resque-retry


【解决方案1】:
class A
  def bar(arg)
  end

  def foo
    bar("baz")
    bar("quux")
  end
end

describe "A" do
  let(:a) { A.new }

  it "Example 1" do
    a.should_receive(:bar).with("baz")
    a.foo # fails 'undefined method bar'
  end
  it "Example 2" do
    a.should_receive(:bar).with("quux")
    a.foo # fails 'received :bar with unexpected arguments
  end
  it "Example 3" do
    a.should_receive(:bar).with("baz")
    a.should_receive(:bar).with("quux")
    a.foo # passes
  end
  it "Example 4" do
    a.should_receive(:bar).with(any_args()).once
    a.should_receive(:bar).with("quux")
    a.foo # passes
  end
end

像存根一样,消息期望替换方法的实现。满足期望后,对象将不再响应方法调用——这将导致“未定义方法”(如示例 1 中所示)。

示例 2 显示了当期望因参数不正确而失败时会发生什么。

示例 3 展示了如何对同一方法的多次调用进行存根 - 按照接收顺序使用正确的参数对每个调用进行存根。

示例 4 表明您可以使用 any_args() 帮助程序在一定程度上减少这种耦合。

【讨论】:

    【解决方案2】:

    使用should_receive 的行为就像一个模拟。对具有不同参数的同一个对象有多个期望是行不通的。如果您将期望更改为Rails.logger.should_receive(:info).exactly(3).times,您的规范可能会过去。

    话虽如此,您可能想要断言比为这些规范记录的内容更相关的内容,然后您可能会有多个有针对性的期望。

    Rails.logger 不会在规格之间被拆毁,因此如果期望在不同的示例中并不重要。为两个单独的示例吐出记录器的对象 ID 说明了这一点:

    it 'does not tear down rails logger' do
      puts Rails.logger.object_id # 70362221063740
    end
    
    it 'really does not' do
      puts Rails.logger.object_id # 70362221063740
    end
    

    【讨论】:

    • Pselbert,谢谢你的回答,但请阅读我的编辑,很抱歉没有早点说清楚。
    • 请查看我对单独示例和 Rails.logger 的编辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 2013-02-17
    • 2021-08-11
    • 1970-01-01
    • 2020-11-25
    相关资源
    最近更新 更多