测试时按特定顺序加载 Rails 夹具
Posted
技术标签:
【中文标题】测试时按特定顺序加载 Rails 夹具【英文标题】:Loading Rails Fixtures in a Specific Order when Testing 【发布时间】:2015-03-18 17:52:04 【问题描述】:有没有办法在运行测试时按特定顺序加载 Rails 固定装置?例如,参加以下课程...
class User < ActiveRecord::Base
has_many :memberships
has_many :groups, through: :memberships
end
class Group < ActiveRecord::Base
has_many :memberships
has_many :users, through: :memberships
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Memberships
有一个数据库级别 外键约束,要求 Users
和 Groups
在创建之前存在。但是,由于 Rails 按字母顺序加载夹具,Memberships
在 Users
之前加载,并且出现错误,说明关系不存在(正确)。
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "memberships" violates foreign key constraint
有没有办法在运行测试时加载 Memberships
之前加载 Users
和 Groups
固定装置?
【问题讨论】:
你在使用命名的灯具吗?见这里:***.com/questions/510195/… 是的,我正在使用命名固定装置。 您是否尝试过设置 FIXTURES 环境变量?和/或在测试中使用“fixtures”命令来指定加载哪些fixture? 我已尝试设置FIXTURE
变量。
FIXTURE 还是 FIXTURES?
【参考方案1】:
您的问题不在于 Rails 运行测试的顺序。我遇到了和你一样的问题,经过几个小时的调试,我意识到 ActiveRecord 实际上确实在插入夹具记录期间禁用了引用完整性,以防止 Postgresql 出现这些类型的错误。
需要注意的是,您的测试数据库用户必须在测试数据库上拥有超级用户权限,ActiveRecord 才能成功禁用夹具所需的引用完整性。
以下是解决问题的方法:
-
使用您的默认超级用户登录 Postgresql(我的是“postgres”)
执行以下命令:
ALTER ROLE yourtestdbuser WITH SUPERUSER;
享受您正常工作的固定装置。
当一个人使用 Postgresql 运行一个测试数据库并且一个没有超级用户角色的用户时,Rails 的下一个版本将会有一个警告(我认为这是非常需要的)。我在a Rails GitHub issue suggesting the warning 上找到了这个。
【讨论】:
完美运行。谢谢! 我在 RDS postgres 实例中遇到了这个问题。 RDS 有什么特别之处吗? RDS 提供的“超级用户”角色是否与普通超级用户相同? 我还应该补充一点,我的 Rails 似乎没有按字母顺序加载固定装置,因为它在 BenchmarkFunds 之前加载 VanguardFunds(依赖于 BenchmarkFunds) 长期的解决方案是明确提供您的固定装置的加载顺序。【参考方案2】:向您的“测试”帐户授予 PostgreSQL 超级用户权限允许 Rails 以它想要的方式工作。在不希望/不可行的情况下......
是的,可以——如果不支持——控制装置的加载顺序和删除(两者都很重要)。
在test/test_helper.rb
:
class ActiveRecord::FixtureSet
class << self
alias :orig_create_fixtures :create_fixtures
end
def self.create_fixtures f_dir, fs_names, *args
# Delete all fixtures that have foreign keys, in an order that
# doesn't break referential integrity.
Membership.delete_all
reset_cache
# If we're adding any user, group fixtures, add them [a] in that
# order, [b] before adding any other fixtures which might have
# references to them.
fs_names = %w(users groups) & fs_names | fs_names
orig_create_fixtures f_dir, fs_names, *args
end
end
使用 Rails 4.2.3 测试,并且仅在使用 fixtures :all
时。
【讨论】:
这为我解决了这个问题(由于某种原因,我无法对 RDS 中的数据库用户进行更改)。非常感谢! 救了我的命!使用 JDBC 和 Informix 连接进行测试。谢谢!【参考方案3】:至少对于 Rails 5,您可以将 fixtures :all
替换为 fixtures %w[users groups memberships]
(在 test/test_helper.rb
中)。它将按该顺序插入它们。但不要忘记任何夹具文件:-)
【讨论】:
感谢 Masa Sakano,我改进了我的答案。以上是关于测试时按特定顺序加载 Rails 夹具的主要内容,如果未能解决你的问题,请参考以下文章
如何在页面加载时按字母顺序对 HTML 列表的内容进行排序? [复制]