【问题标题】:How to unit test a module (a resque scheduler job) in rspec如何在 rspec 中对模块(resque 调度程序作业)进行单元测试
【发布时间】:2014-04-23 21:03:03
【问题描述】:

我有一个(简化的)模块:(/app/jobs/checkpulse.rb)

module CheckPulse
  @queue = :heartbeat
  def self.perform()
    Machine.all.each do |machine|
      machine.update_columns(active_alarm: true) #do not want to touch updated_at
    end
  end
end

我可以在 Rails 控制台中使用它,它会按预期更改所有机器。

我正在尝试编写一个规范来测试它: (/spec/jobs/checkpulse_spec.rb)

require "spec_helper"
require_relative '../../app/jobs/checkpulse'

describe "CheckPulse" do

  let(:user) { FactoryGirl.create(:user) }
  let!(:machine) { FactoryGirl.create(:machine, user: user, heartbeat_timeout: 5) }

  it "should change the machine to alarm mode" do
    CheckPulse.perform
    expect(machine.active_alarm).to be_true
  end
end

此测试每次都失败。我在 CheckPul​​se 模块中使用了 puts 来检查它,它在模块内部具有预期的行为,但是当它从模块返回时,机器并没有改变。

我试过mixing the module into a dummy class,但也没有用。我还尝试在测试环境中运行 rails 控制台,看看是否是环境问题,但模块在那里也可以正常工作。

我花了一整天的时间,请帮忙!

【问题讨论】:

  • 可能很傻,但是如果你在做期望之前重新加载machine (machine.reload),它会起作用吗?它在修改数据库中的状态之前加载了machine var,所以也许它只需要刷新?
  • 好的,见下文,谢谢!

标签: ruby-on-rails unit-testing rspec resque resque-scheduler


【解决方案1】:

首先,尝试遵循 ruby​​ 和 rails 的约定。如果你调用模块CheckPulse,它的文件名应该是check_pulse.rb。它将帮助您避免require_relative。其次,在规范和模块中,您与不同的 ruby​​ 对象进行交互,这些对象都写入数据库中的同一行。如果您更新一个对象,另一个对象将不会同步更新。您需要通过调用规范中的machine.reload 手动重新加载它。

还有一些代码提示:

  • 永远不要使用all.each。如果您的数据库中有 2k+ 条记录,它将卡住。要迭代所有数据库记录,请使用find_each
  • 您可以使用update_all -> Machine.update_all(:column_1 => value_1, :column_2 => value_3) 更新所有记录,而不是加载并更新每条记录
  • 避免在没有参数的方法中使用圆括号

【讨论】:

  • 期望(machine.reload.active_alarm).to be_true 工作!谢谢!我还重命名了文件并更改为 self.perform - 没有()。现在调查 find_each。
  • 更改为 Machine.all.find_each do |machine| .那么,这是否与 all.each 相同,只要记录数小于批量大小(默认 1000)?
  • 将文件名更改为 check_pulse.rb 并神奇地消除了 require_relative。
猜你喜欢
  • 2018-10-28
  • 2011-07-23
  • 2012-09-12
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多