测试时按特定顺序加载 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 有一个数据库级别 外键约束,要求 UsersGroups 在创建之前存在。但是,由于 Rails 按字母顺序加载夹具,MembershipsUsers 之前加载,并且出现错误,说明关系不存在(正确)。

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  insert or update on table "memberships" violates foreign key constraint

有没有办法在运行测试时加载 Memberships 之前加载 UsersGroups 固定装置?

【问题讨论】:

你在使用命名的灯具吗?见这里:***.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 列表的内容进行排序? [复制]

RSpec 中的夹具

带有载波的 Rails 3 测试夹具?

无论我使用哪种顺序,Rails 5 中的引导/jQuery 加载顺序都会中断

为 Rails 加载配置文件的顺序是啥?

在 Rails 控制台中加载和使用夹具