【问题标题】:Ruby on Rails Testing - ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "xxx_xxxx_xxxx_pkey"Ruby on Rails 测试 - ActiveRecord::RecordNotUnique: PG::UniqueViolation: 错误:重复键值违反唯一约束“xxx_xxxx_xxxx_pkey”
【发布时间】:2021-02-11 23:01:30
【问题描述】:

我有以下型号。我正在使用 Rails 6.0.3.2 (Ruby 2.7.1p83) 并使用 Minitest 作为测试引擎

class AuthContentType < ApplicationRecord
  has_many :auth_permissions
end
class AuthGroup < ApplicationRecord
  has_many :auth_group_permissions
  has_many :auth_permissions, through: :auth_group_permissions
end
class AuthGroupPermission < ApplicationRecord
  belongs_to :auth_group
  belongs_to :auth_permission
end
class AuthPermission < ApplicationRecord
  belongs_to :auth_content_type
  has_many :auth_user_permissions
  has_many :users, through: :auth_user_permissions
  has_many :auth_group_permissions
  has_many :auth_groups, through: :auth_group_permissions
end

当我运行 > rails test test\controllers\XXXX_controller.rb -n test_should_get_home 我收到以下错误:

Run options: -b -n test_should_get_home --seed 27312                                                                                                                                         
                                                                                                                                                                                             
# Running:                                                                                                                                                                                   
                                                                                                                                                                                             
E                                                                                                                                                                                            
                                                                                                                                                                                             
Error:                                                                                                                                                                                       
GdControllerTest#test_should_get_home:                                                                                                                                                       
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "auth_content_types_pkey"                                                         
DETAIL:  Key (id)=(980190962) already exists.                                                                                                                                                
                                                                                                                                                                                             
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:92:in `exec'                                         
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:92:in `block (2 levels) in execute'                  
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'                                                          
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'                                                
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:91:in `block in execute'                             
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract_adapter.rb:722:in `block (2 levels) in log'                                   
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'                      
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'                                     
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'                                 
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'                                     
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'                                          
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract_adapter.rb:721:in `block in log'                                              
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/notifications/instrumenter.rb:24:in `instrument'                                                         
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract_adapter.rb:712:in `log'                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:90:in `execute'                                      
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:170:in `execute_batch'                               
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:370:in `block (3 levels) in insert_fixtures_set'       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `block in transaction'                          
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/transaction.rb:280:in `block in within_new_transaction'                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'                      
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'                                     
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'                                 
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'                                     
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'                                          
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/transaction.rb:278:in `within_new_transaction'                                
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `transaction'                                   
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:369:in `block (2 levels) in insert_fixtures_set'       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/postgresql/referential_integrity.rb:19:in `disable_referential_integrity'              
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:368:in `block in insert_fixtures_set'                  
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:480:in `with_multi_statements'                         
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:367:in `insert_fixtures_set'                           
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/fixtures.rb:608:in `block in insert'                                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/fixtures.rb:599:in `each'                                                                                  
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/fixtures.rb:599:in `insert'                                                                                
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/fixtures.rb:585:in `read_and_insert'                                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/fixtures.rb:545:in `create_fixtures'                                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/test_fixtures.rb:205:in `load_fixtures'                                                                    
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/test_fixtures.rb:118:in `setup_fixtures'                                                                   
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.2/lib/active_record/test_fixtures.rb:8:in `before_setup'                                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.2/lib/active_support/testing/setup_and_teardown.rb:40:in `before_setup'                                                       
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/actionpack-6.0.3.2/lib/action_dispatch/testing/integration.rb:322:in `before_setup'                                                               
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activejob-6.0.3.2/lib/active_job/test_helper.rb:45:in `before_setup'                                                                              
    C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.0.3.2/lib/rails/test_help.rb:48:in `before_setup'                                                                                      
                                                                                                                                                                                             
                                                                                                                                                                                             
rails test test/controllers/gd_controller_test.rb:4                                                                                                                                          
                                                                                                                                                                                             
.                                                                                                                                                                                            
                                                                                                                                                                                             
Finished in 2.872201s, 0.6963 runs/s, 0.3482 assertions/s.                                                                                                                                   
2 runs, 1 assertions, 0 failures, 1 errors, 0 skips 

我可以在这方面得到帮助吗?一直在尝试执行一些建议的解决方案。但这对我没有帮助。

解决方案:1(在控制台中运行)

    ActiveRecord::Base.connection.tables.each do |t|
      ActiveRecord::Base.connection.reset_pk_sequence!(t)
    end

我的测试/test_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'

class ActiveSupport::TestCase
  # Run tests in parallel with specified workers
  parallelize(workers: :number_of_processors, with: :threads)

  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...

end

我的测试\控制器\converge_controller_test.rb

require 'test_helper'

class ConvergeControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    #get converge_home_url
    get home_url
    #assert_response :success
    assert_redirected_to new_user_session_url
  end

end

我的测试\控制器\gd_controller_test.rb

require 'test_helper'

class GdControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get gd_home_url
    #assert_response :success
    assert_redirected_to new_user_session_url
  end

end

【问题讨论】:

  • 该错误表明您在加载测试夹具时违反了表 auth_content_types 的主键约束。夹具通过从夹具标签构建校验和来使用稳定的 ID。要么您以某种方式多次加载固定装置,要么清理不起作用。请将您的lib/test_helper.rbtest/controllers/gd_controller_test.rb 的内容贴出来,他们需要找到错误的确切来源。
  • 我在这里添加了 'test_helper.rb' 和 test/controllers/gd_controller_test.rb 脚本

标签: ruby-on-rails ruby postgresql testing


【解决方案1】:

您的数据库中可能有唯一索引。你添加一个任务并运行

rake 数据库:correction_seq_id

rails g 任务数据库correction_seq_id

然后生成像 lib/tasks/database.rake 这样的文件

你应该把这个块:

namespace :database do
    desc "Correction of sequences id"
    task correction_seq_id: :environment do
        ActiveRecord::Base.connection.tables.each do |t|
            ActiveRecord::Base.connection.reset_pk_sequence!(t)
        end
    end
end

【讨论】:

【解决方案2】:

知道我的机器有 Windows 操作系统,我通过执行以下操作解决了问题:

我把这行注释掉了

parallelize(workers: :number_of_processors, with: :threads)

来自我的 test_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'

class ActiveSupport::TestCase
  # Run tests in parallel with specified workers
  # parallelize(workers: :number_of_processors, with: :threads)

  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...

end

【讨论】:

  • Windows 应该支持并行测试,因为 Rails 应该为每个工作人员创建不同的测试数据库,所以不应该有任何冲突。也许这是一个并行测试的错误,只发生在 Windows 上。您可以尝试在 Rails 问题跟踪器中报告问题:github.com/rails/rails/issues
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 2015-03-24
  • 2020-02-15
  • 1970-01-01
  • 2016-07-27
  • 2011-10-17
相关资源
最近更新 更多