测试时按特定顺序装载导轨夹具

时间:2022-09-20 19:01:59

Is there a way to load Rails fixtures in a specific order while running tests? For example, take the following classes...

有没有办法在运行测试时按特定顺序加载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 have a database level foreign key constraint requiring Users and Groups to be present before they can be created. However, because Rails loads fixture alphabetically, Memberships are loaded before Users, and an error occurs stating the relationships do not exist (rightly so).

成员资格具有数据库级外键约束,要求用户和组在创建之前存在。但是,由于Rails按字母顺序加载fixture,因此会在Users之前加载Membership,并且会发生错误,指出关系不存在(正确地说是这样)。

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

Is there a way to load the Users and Groups fixtures before loading Memberships while running tests?

有没有办法在运行测试时加载成员资格之前加载用户和组夹具?

2 个解决方案

#1


37  

Your problem isn't the order that Rails is running your tests. I had the same issue as you, and after debugging for a few hours realized that ActiveRecord actually DOES disable referential integrity during insertion of fixture records to prevent these types of errors for Postgresql.

您的问题不是Rails运行测试的顺序。我遇到了和你一样的问题,经过几个小时的调试后发现,ActiveRecord实际上在插入夹具记录时会禁用参照完整性,以防止Postgresql出现这些类型的错误。

The catch is that your test database user must have superuser privileges on the test db for ActiveRecord to successfully disable referential integrity as needed for fixtures.

问题在于,您的测试数据库用户必须拥有ActiveRecord测试数据库的超级用户权限才能成功禁用fixture的参照完整性。

Here's how you fix your issue:

以下是解决问题的方法:

  1. Log into Postgresql with your default superuser (mine is "postgres")
  2. 使用默认超级用户登录Postgresql(我的是“postgres”)
  3. Perform the following command:

    执行以下命令:

    ALTER ROLE yourtestdbuser WITH SUPERUSER;
    
  4. Enjoy your properly working fixtures.

    享受你正常工作的灯具。

The next release of Rails will have a warning (which I think is much needed) when a person is running a test database with Postgresql and a user without a superuser role. I found this on a Rails GitHub issue suggesting the warning.

当一个人使用Postgresql运行测试数据库和没有超级用户角色的用户时,Rails的下一个版本将发出警告(我认为非常需要)。我在一个Rails GitHub问题上发现了这个警告。

#2


9  

Granting PostgreSQL superuser privileges to your "test" account allows Rails to work the way it wants to work. In cases where this is not desired/feasible...

向您的“测试”帐户授予PostgreSQL超级用户权限允许Rails以其想要的方式工作。在不希望/不可行的情况下......

Yes, it is possible -- if not supported -- to control the order in which fixtures are loaded and deleted (both of which are important).

是的,如果不支持,可以控制加载和删除灯具的顺序(两者都很重要)。

In test/test_helper.rb:

在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

Tested with Rails 4.2.3, and only when using fixtures :all.

使用Rails 4.2.3进行测试,并且仅在使用fixture时:all。

#1


37  

Your problem isn't the order that Rails is running your tests. I had the same issue as you, and after debugging for a few hours realized that ActiveRecord actually DOES disable referential integrity during insertion of fixture records to prevent these types of errors for Postgresql.

您的问题不是Rails运行测试的顺序。我遇到了和你一样的问题,经过几个小时的调试后发现,ActiveRecord实际上在插入夹具记录时会禁用参照完整性,以防止Postgresql出现这些类型的错误。

The catch is that your test database user must have superuser privileges on the test db for ActiveRecord to successfully disable referential integrity as needed for fixtures.

问题在于,您的测试数据库用户必须拥有ActiveRecord测试数据库的超级用户权限才能成功禁用fixture的参照完整性。

Here's how you fix your issue:

以下是解决问题的方法:

  1. Log into Postgresql with your default superuser (mine is "postgres")
  2. 使用默认超级用户登录Postgresql(我的是“postgres”)
  3. Perform the following command:

    执行以下命令:

    ALTER ROLE yourtestdbuser WITH SUPERUSER;
    
  4. Enjoy your properly working fixtures.

    享受你正常工作的灯具。

The next release of Rails will have a warning (which I think is much needed) when a person is running a test database with Postgresql and a user without a superuser role. I found this on a Rails GitHub issue suggesting the warning.

当一个人使用Postgresql运行测试数据库和没有超级用户角色的用户时,Rails的下一个版本将发出警告(我认为非常需要)。我在一个Rails GitHub问题上发现了这个警告。

#2


9  

Granting PostgreSQL superuser privileges to your "test" account allows Rails to work the way it wants to work. In cases where this is not desired/feasible...

向您的“测试”帐户授予PostgreSQL超级用户权限允许Rails以其想要的方式工作。在不希望/不可行的情况下......

Yes, it is possible -- if not supported -- to control the order in which fixtures are loaded and deleted (both of which are important).

是的,如果不支持,可以控制加载和删除灯具的顺序(两者都很重要)。

In test/test_helper.rb:

在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

Tested with Rails 4.2.3, and only when using fixtures :all.

使用Rails 4.2.3进行测试,并且仅在使用fixture时:all。