Метод модуля-заглушки внутри задачи rake с помощью rspect

#ruby-on-rails #ruby #rspec #rake

#ruby-on-rails #ruby #rspec #rake

Вопрос:

Я работаю в проекте с использованием RoR и Rspect.

У меня есть задача rake, которая использует метод из другого вызываемого Gem When2top::iterate . Этот метод повторяется в течение указанного времени.

   task :log_stats, [:entity_name, :duration_limit] => [:environment] do |_, args|
    include When2stop
    entity_name = args[:entity_name]
    duration = args[:duration_limit].to_i
    index_data = (Wh2find::INDEXABLES.find entity_name: entity_name).first
    entity_class = index_data[:entity]
    iterate for: duration.minutes do
      byebug
      stats = entity_class.get_stats
      values = Hash[stats.collect { |item| [item[:index_status], item[:count]] }]
      values.each { |k, val|  NewRelic::Agent.record_metric("Wh2find/#{entity_name}/#{k}", val) }
    end
  end
 

Итак, я хочу написать тест для задачи, которая использует этот метод, но я не использовал его на самом деле, потому что это подразумевает замедление теста (мне нужно подождать определенное время) и не знаю, сколько раз будет выполняться логика внутри блока.

У меня есть свои спецификации для этой задачи, но я не могу заглушить метод модуля.

 require 'rails_helper'

Rails.application.load_tasks

include When2stop

describe :wh2find do
  describe :log_stats do
    it 'should log stats' do
      task = Rake::Task['wh2find:log_stats']
      entity_name = TestEntity.class
      duration = "1"

      stub_const "Wh2find::INDEXABLES", [
        {
          entity_name: 'entity',
          entity: TestEntity,
          fields_to_index: {
            name: {
              weight: 1
            }
          }
        }
      ]

      expect(task).stub_chain(:iterate) do |dur, amp;block|
        byebug
        expect(dur).to eq(duration.minutes)

        expect(TestEntity).to receive(:get_stats).and_return(
          [
            {
              _id: 0,
              count: 10,
              index_status: 'to_index'
            },
            {
              _id: 1,
              count: 5,
              index_status: 'to_reindex'
            },
            {
              _id: 2,
              count: 1054,
              index_status: 'indexed'
            },
          ]
        )
        new_relic_agent = double('NewRelic::Agent').as_stubbed_const
        expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/to_index", 10)
        expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/to_reindex", 5)
        expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/indexed", 1054)
        block.call()
      end

      task.invoke(entity_name, duration)
    end

  end
end
 

Есть идеи о том, как я мог бы заглушить этот метод и утвердить итеративную логику?

Заранее спасибо!

Комментарии:

1. Вы могли бы рассмотреть возможность использования драгоценного камня Timecop, который позволяет вам перемещать и масштабировать время, но должна быть какая-то альтернатива этому драгоценному камню, который имеет встроенную поддержку для тестирования.

2. Что это за драгоценный камень? Этого нет в RubyGems. Если это ваш личный драгоценный камень, то вам следует добавить несколько помощников по тестированию в сам драгоценный камень.

3. @max спасибо, да, я мог бы использовать Timecop для быстрого завершения метода, но моя цель — не проверить, работает ли итерация, но она вызывается, так что это не реальное решение.

4. Как говорит @BroiSatse, когда 2stop — мой драгоценный камень, он приватный, но я мог бы сделать это общедоступным. Но я не понимаю, что я мог бы добавить в свой gem, чтобы сделать его более удобным для тестирования. Вот ссылка на репозиторий gem: github.com/wh-2/when2stop Вот мой проект: github.com/wh-2/wh2find

5. Это будет очень сложно протестировать, поскольку вам придется заглушить метод в экземпляре задачи rake. Но на самом деле это только верхушка айсберга — я бы беспокоился об использовании памяти при выполнении этого кода в течение N минут.