Как выполнить модульное тестирование модуля (задание Resque Scheduler) в rspec

У меня есть (упрощенный) модуль: (/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

Этот тест не проходит каждый раз. Я использовал путы внутри модуля CheckPulse, чтобы проверить его, и он имеет ожидаемое поведение внутри модуля, но когда он возвращается из модуля, машина не изменилась.

Я попытался смешать модуль в фиктивный класс, но это тоже не сработало. Я также попытался запустить консоль rails в тестовой среде, чтобы проверить, не является ли это проблемой среды, но модуль там тоже работал нормально.

Я провел целый день на этом, пожалуйста, помогите!

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)
  • избегать круглых скобок в методах без аргументов
Другие вопросы по тегам