【问题标题】:Testing my Rake task in Rails 4 loses an instance variable在 Rails 4 中测试我的 Rake 任务会丢失一个实例变量
【发布时间】:2015-05-23 16:27:01
【问题描述】:

我的 Rake 任务测试无法通过;似乎在 rake 任务运行后我丢失了我的实例变量,因为它返回 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

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

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 rspec


    【解决方案1】:

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

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

    因为find_by 返回的是ActiveRecord 而不是ActiveRelation

    【讨论】:

    • 谢谢你的回答,也许我只是有点困惑,因为我认为我从数据库中获取记录并将其分配给@update_event 是在我运行我的 rake 任务之前?
    • 不。 where 返回一个查询对象(即一个ActiveRelation),直到你调用一个执行执行的方法(例如firstall)才会执行。
    • 哇,不知道,这一切都清楚了,谢谢
    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 2015-09-23
    • 2018-06-15
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多