Почему в моем тесте дважды запускается задача rake?

У меня есть тест с граблями, который я настроил, следуя единственным примерам, которые я смог найти в Интернете.

Это выглядит так:

require 'test_helper'
require 'minitest/mock'
require 'rake'

class TestScrapeWelcome < ActiveSupport::TestCase
  def setup
    Rake.application.init
    Rake.application.load_rakefile

    @task = Rake::Task['scrape:scrape']
    @task.reenable
  end

  def teardown
    Rake::Task.clear
  end

  test "scraping text and sending to elasticsearch" do
    mocked_client = Minitest::Mock.new
    get_fixtures.each_with_index do |arg,i|
      mocked_client.expect :index, :return_value, [index: "test", type: 'welcome', id: i, body: arg]
    end
    Elasticsearch::Model.stub :client, mocked_client do
      @task.invoke
    end
    assert mocked_client.verify
  end

  private

  def get_fixtures
    (0..11).map { |i|
      File.read("test/fixtures/scrape/index_#{i}.json")
    }
  end

end

Но после того, как задание запускается, оно снова запускается, и я ничего не делаюputs печатает до и после @task.invoke показать, что задача запускается только один раз).

3 ответа

Решение

Оказывается, что rake уже требуется и инициализируется при запуске теста, поэтому необходимо удалить все следующие строки или дважды определить задачу и выполнить дважды, даже если вы вызываете ее только один раз.

require 'minitest/mock'
require 'rake'
...
Rake.application.init
Rake.application.load_rakefile

Обновленный ответ для rails 5.1 (с использованием minitest):

Я обнаружил, что мне нужно следующее, чтобы загрузить задачи один раз и только один раз:

MyAppName::Application.load_tasks if Rake::Task.tasks.empty?

В качестве альтернативы добавьте MyAppName::Application.load_tasks к вашему test_helper, если вы не возражаете против загрузки задач, даже если вы запускаете отдельные тесты, которые в них не нуждаются.

(Замените MyAppName именем вашего приложения)

Я пробовал ответ @iheggie, но он работал так, что тесты действительно запускались один раз, но любая другая задача ломалась с Don't know how to build task '<task_name_like_db_migrate>'.

Я все еще использую Rails 3.2. Оказалось, что заранее была загружена пара задач, поэтомуRake::Task.tasks.empty? никогда не был trueи все остальные полезные задачи не загружались. Я повозился с ним, и эта версия работает для меня прямо сейчас:

Rake::Task.clear if Rails.env.test?
MyAppName::Application.load_tasks

Надеюсь, это кому-нибудь поможет.

Решение, которое работает для тестирования задач Gem, который был сделан Railtie поэтому он может добавлять задачи в приложение Rails:

Не определяйте Railtie в тестовом режиме, когда вы также определяете Rails::Application класс в spec_helper.rb (что позволяет вашим тестам звонить Rails.application.load_tasks). В противном случае файл Rake будет загружен один раз как Railtie и один раз как Engine:

class Railtie < Rails::Railtie
  rake_tasks do
    load 'tasks/mygem.rake'
  end
end unless Rails.env.test? # Without this condition tasks under test are run twice

Другим решением было бы поместить условие в файл Rake, чтобы пропустить определения задач, если файл уже был загружен.

Другие вопросы по тегам