Minitest:相关 AR 模型的固定装置导致 ActiveRecord::InvalidForeignKey:PG::ForeignKeyViolation 当测试为 运行

Minitest: fixtures for associated AR models results in ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation when tests are run

我 运行 遇到了 Minitest 和关联 ActiveRecord 模型 (Rails. 4.2.3) 的问题。

以下是两个模型:

# vanguard_fund.rb
class VanguardFund < ActiveRecord::Base
  belongs_to :benchmark_fund
  ...
end

# benchmark_fund.rb
class BenchmarkFund < ActiveRecord::Base
  has_many :vanguard_funds
end

非常简单。现在是固定装置:

# vanguard_funds.yml
vf1:
  name: Vanguard Fund 1
  benchmark_fund: bm1

# benchmark_funds.yml    
bm1:
  name: Benchmark Fund 1

现在我在 运行 任何测试时收到以下错误:

ERROR["test_#name_returns_the_name_of_the_VanguardFund", BaseTest, 2015-06-08 13:39:28 +0000]
 test_#name_returns_the_name_of_the_VanguardFund#BaseTest (1433770768.22s)
ActiveRecord::InvalidForeignKey:         ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  insert or update on table "vanguard_funds" violates foreign key constraint "fk_rails_994ab6fe75"
        DETAIL:  Key (benchmark_fund_id)=(479852872) is not present in table "benchmark_funds".
        : INSERT INTO "vanguard_funds" ("name", "created_at", "updated_at", "id", "benchmark_fund_id") VALUES ('Vanguard Fund 1', '2015-09-04 16:48:23', '2015-09-04 16:48:23', 263706224, 479852872)
            test_after_commit (0.4.1) lib/test_after_commit.rb:15:in `block in transaction_with_transactional_fixtures'
            test_after_commit (0.4.1) lib/test_after_commit.rb:9:in `transaction_with_transactional_fixtures'

一个基准基金 ID (479852872),但是创建 VanguardFund 时似乎在 BenchmarkFunds table 中找不到该记录??

有什么建议吗?

我相信 Rails 试图在加载固定装置之前禁用参照完整性检查。如果您的 PostgreSQL 用户不是超级用户,那么这将无提示地失败,随后夹具加载将失败并出现您看到的 ActiveRecord::InvalidForeignKey 错误。

解决方法是让您的 PostgreSQL 用户成为超级用户。使用特权帐户连接到 PostgreSQL,然后发出 ALTER USER ... WITH SUPERUSER 命令。

在 Ubuntu,我是这样做的:

su -l postgres -c "psql -c 'alter user jenkins with superuser;'"

在这种情况下,jenkins 是未能通过 运行 Rails 测试的用户。这解决了我的问题。

edge version of the Rails testing guide中对此有解释(强调已添加):

In order to remove existing data from the database, Rails tries to disable referential integrity triggers (like foreign keys and check constraints). If you are getting annoying permission errors on running tests, make sure the database user has privilege to disable these triggers in testing environment. (In PostgreSQL, only superusers can disable all triggers. Read more about PostgreSQL permissions here).