测试迁移时如何暂时禁用"needs_migration?"检查?



我已经编写了规范来测试我的迁移,但当我运行它时,我遇到了一个错误:

ActiveRecord::PendingMigrationError:
Migrations are pending. To resolve this issue, run:
bin/rake db:migrate RAILS_ENV=test

我曾尝试在before部分禁用迁移检查,但该检查在所有测试之前都在运行。

如何出于测试目的禁用迁移检查?

测试Rails迁移有点麻烦,所以我宁愿退一步思考是否需要在Rails迁移中进行测试。

基本上有两种不同类型的迁移

架构迁移

主要使用Rails内置函数。除非你做一些手工制作的SQL,否则我不会去测试它,并且相信这里的框架。

数据迁移

数据迁移用于回填或更改数据。由于数据是您最有价值的资产之一,丢失或损坏数据是非常痛苦的,我绝对建议您编写数据迁移测试。

如前所述,测试迁移有点麻烦,所以我会尝试在它自己的(服务(类中抽象数据迁移代码。类似的东西

class DataMigration::UpdateUsername
def self.run
new.run
end
def run
User.all do |batch|
user.update(name: user.name.capitalize)
end
end
end

现在,您可以像下面这样的普通类一样测试数据迁移:

it 'does capitalize the name' do
user = create(:user, name: 'name')
DataMigration::UpdateUsername.run
expect(user.reload.name).to eq('NAME')
end

现在我们可以在Rails迁移中使用这个类,或者只在Rake任务中使用它。在Rake任务中使用它还有一个优点,即我们可以传入参数,并行运行多个数据迁移(例如,您有一个大数据集(,甚至可以在后台作业中使用,而在Rails迁移中是无法做到的。

示例

class DataMigration::UpdateUsername
def initialize(start_id:, finish_id:)
@start_id = start_id
@finish_id = finish_id
end
def run
User.find_in_batches(start: start_id, finish: finish_id) do |batch|
batch.each do |user|
user.update(name: user.name.capitalize)
end
end
end
end

现在我们可以为这个创建一个自定义任务

namespace :db do
desc "Runs user data migration"
task :update_user, [:start, :finish] do |task, args|
DataMigration::UpdateUsername.new(start_id: args[:start], finish_id: args[:finish])
end
end
rake db:update_user[0, 10000]
rake db:update_user[10000, 20000]
# ...

config/environments/test.rb中添加行

config.active_record.migration_error = false 

最新更新