为什么我的rake任务在我的测试中运行了两次?

时间:2015-07-25 02:35:18

标签: ruby-on-rails rake minitest rake-task

我有一个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之前和之后打印显示该任务只运行一次。)

4 个答案:

答案 0 :(得分:10)

事实证明,在测试运行时已经需要并初始化rake,因此需要删除所有以下行,或者任务被定义两次并运行两次,即使您只调用一次。

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

答案 1 :(得分:1)

更新了rails 5.1(使用minitest)的答案:

我发现我需要以下内容才能一次加载任务一次:

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

或者,如果您不介意加载任务,即使运行不需要它们的单个测试,也可以将MyAppName::Application.load_tasks添加到test_helper中。

(将MyAppName替换为您的应用程序名称)

答案 2 :(得分:0)

一个解决方案,用于测试已成为Railtie的Gem的任务,以便它可以向Rails应用添加任务:

当您在Railtie中定义Rails::Application课程时,不要在测试模式中定义spec_helper.rb(允许您的测试调用Rails.application.load_tasks })。否则,Rake文件将作为Railtie加载一次,并作为引擎加载一次:

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文件中放置一个条件,以便在文件已经加载时跳过任务定义。

答案 3 :(得分:0)

我尝试了@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

希望这对任何人都有帮助。