在 Rails 4 中测试我的 Rake 任务丢失了一个实例变量

Testing my Rake task in Rails 4 loses an instance variable

我无法通过我的 Rake 任务测试;似乎在 rake 任务 运行 之后我失去了我的实例变量,因为它 returns nil 而在 Rake 任务是 运行 之前我得到了一个记录

所以在我所有的测试之前我有这个配置设置

ENV['RAILS_ENV'] ||= 'test'
require 'spec_helper'
require 'rake'
load File.expand_path('../../lib/tasks/create_events.rake', __FILE__)
load File.expand_path('../../lib/tasks/update_event.rake', __FILE__)
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.before(:suite) do
   DatabaseCleaner.strategy = :truncation
   DatabaseCleaner.clean_with :truncation
   Rake::Task.define_task(:environment)
   Rake::Task['create_events:create_event_data'].invoke
  end

  config.after(:suite) do
    DatabaseCleaner.clean
  end
end

我的规格文件是这样设置的

require "rails_helper"
require 'rake'

RSpec.describe "update_event:next_event_date Rake Task" do

 it "should change the next occurrence date" do
  @update_event = Event.where(next_occurrence: Date.today)
  # So here @update_event returns 1 record (Active Record Relation)
  Rake::Task.define_task(:environment)
  Rake::Task['update_event:next_event_date'].invoke
  # By here @update_event = nil (Active Record Relation = [])

   case @update_event.first.weekly_frequency
   when 1
    expect(@update_event.first.next_occurrence).to eq(Date.today + 7.days)
   when 2
    expect(@update_event.first.next_occurrence).to eq(Date.today + 14.days)
   when 6
    expect(@update_event.first.next_occurrence).to eq(Date.today + 42.days)
   end
 end
end

这背后的原因是什么?我该如何正确测试?

我实际的 Rake 任务是这样的

namespace :update_event do
 desc "Update next_occurrence date for an event"
  task next_event_date: :environment do
   @event = Event.where(next_occurrence: Date.today)
    @event.each do |e|
     if e.weekly_frequency == 1
      e.update_attributes next_occurrence: Date.today + 7.days
     elsif e.weekly_frequency == 2
      e.update_attributes next_occurrence: Date.today + 14.days
     elsif e.weekly_frequency == 6
      e.update_attributes next_occurrence: Date.today + 42.days
     end
   end
  end
 end

编辑

所以我稍微修改了我的规格

require "rails_helper"
require 'rake'

RSpec.describe "update_event:next_event_date Rake Task" do

it "should change the next occurrence date" do
  @update_event = Event.where(next_occurrence: Date.today)
  event_id = Event.find(@update_event.first.id)
  Rake::Task.define_task(:environment)
  Rake::Task['update_event:next_event_date'].invoke
  @after_update = Event.find(event_id)
   case @after_update.weekly_frequency
   when 1
    expect(@after_update.next_occurrence).to eq(Date.today + 7.days)
   when 2
    expect(@after_update.next_occurrence).to eq(Date.today + 14.days)
   when 6
    expect(@after_update.next_occurrence).to eq(Date.today + 42.days)
  end
 end    
end

这通过了,但我不确定为什么我丢失了我的第一个实例变量。

您不是 "losing" 您的实例变量。您的实例变量是一个查询,它将在您的 rake 任务之前和之后产生不同的结果。您修改后的测试在 rake 任务之前执行查询,并将从结果派生的内容保存在局部变量中(即第一条记录的 ID)。您可以通过如下方式保存事件来达到类似的效果:

@update_event = Event.find_by(next_occurrence: Date.today)

因为 find_by returns ActiveRecord 而不是 ActiveRelation