【问题标题】:Rspec Test Fail After Migrating from Sqlite to Postgresql从 Sqlite 迁移到 Postgresql 后 Rspec 测试失败
【发布时间】:2017-05-26 23:12:36
【问题描述】:

我正在使用 Cloud 9 + Ruby on Rails + Rspec + Capybara + FactoryGirl + DatabaseCleaner。到目前为止,我一直在使用 sqlite 进行开发,并且遇到了无法使用 sqlite 的图表功能。所以我迁移到使用 Postgresql。

现在,当我运行 rspec 测试时,它失败了。我可以恢复使用 sqlite 并且此时测试运行良好。

这是我收到的错误之一:

Failures:

  2) Property creation has been completed successfully
     Failure/Error: @property = FactoryGirl.create(:property)

     ActiveRecord::InvalidForeignKey:
       PG::ForeignKeyViolation: ERROR:  insert or update on table "properties" violates foreign key constraint "fk_rails_680868ce5b"
       DETAIL:  Key (property_type_id)=(1) is not present in table "property_types".
       : INSERT INTO "properties" ("address", "city", "state", "zip", "property_type_id", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/configuration.rb:18:in `block in initialize'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:15:in `create'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `tap'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
     # /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
     # ./spec/features/property_spec.rb:10:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # PG::ForeignKeyViolation:
     #   ERROR:  insert or update on table "properties" violates foreign key constraint "fk_rails_680868ce5b"
     #   DETAIL:  Key (property_type_id)=(1) is not present in table "property_types".
     #   /usr/local/rvm/gems/ruby-2.3.0/gems/factory_girl-4.8.0/lib/factory_girl/configuration.rb:18:in `block in initialize'

我认为这个错误正在发生,因为在创建时,property_types 表中不存在 ID 为 1 的 property_type_id 1。相反,property_types 的 ID 是 2。似乎 ID 列在每个示例之后都没有重置回 1。

这是我的 rails_helper.rb:

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)

abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'capybara/rails'

include Warden::Test::Helpers
Warden.test_mode!


ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = false
  config.before(:suite) { DatabaseCleaner.clean_with(:truncation) }
  config.before(:each) { DatabaseCleaner.strategy = :transaction }
  config.before(:each, :js => true) { DatabaseCleaner.strategy = :truncation }
  config.before(:each) { DatabaseCleaner.start }
  config.after(:each) { DatabaseCleaner.clean }
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
  config.include FactoryGirl::Syntax::Methods
end

这是 Database.yml 文件:

default: &default
      adapter: postgresql
      encoding: unicode
      pool: 5
      username: ubuntu
      password: xxxxxxxx
      template: template0

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

production:
  <<: *default
  database: app_production

这是失败的测试之一:

require 'rails_helper'

describe 'Property' do

    describe 'creation' do

        it "has been completed successfully" do            
            @user = FactoryGirl.create(:user)            
            login_as(@user, :scope => :user)  
            FactoryGirl.create(:property_type)
            @property = FactoryGirl.create(:property)
            visit new_property_path
            fill_in "property_address", with: @property.address
            fill_in "property_city", with: @property.city
            fill_in "property_state", with: @property.state
            fill_in "property_zip", with: @property.zip
            fill_in "property_units", with: @property.units  
            click_button "Save"  
            expect(@property.reload.address).to eq(@property.address)
            expect(@property.reload.city).to eq(@property.city)
            expect(@property.reload.state).to eq(@property.state)
            expect(@property.reload.zip).to eq(@property.zip)
            expect(@property.reload.units).to eq(@property.units)
    end
end

这里是属性工厂:

FactoryGirl.define do

   factory :property do
      address "111 Test Dr" 
      city "Test"
      state "TS"
      zip "999999"
      property_type_id 1
      user_id 1
   end
end

这是用户工厂:

FactoryGirl.define do

   factory :user do
        email "tester@tester.com"
        first_name "Test"
        last_name "Test"
        password "abcd1234"
        password_confirmation "abcd1234"       
   end
end

这是属性类型工厂:

FactoryGirl.define do

  factory :property_type do
    name "Single Family"
  end
end

任何帮助将不胜感激,因为我已经研究这个问题好几天了。

【问题讨论】:

  • 您有外键约束错误。 PG::ForeignKeyViolation: ERROR: insert or update on table "properties" violates foreign key constraint "fk_rails_680868ce5b"。你能把所有migrations@

标签: ruby-on-rails postgresql sqlite rspec database-cleaner


【解决方案1】:

在 Property Factory 中,property_type_id 总是引用 1,如果在 property_type 表中找不到它会引发外键错误。

如果property与property_type有关系,你可以将其更改为使用关联,它会动态创建property_type。

FactoryGirl.define do

   factory :property do
      address "111 Test Dr" 
      city "Test"
      state "TS"
      zip "999999"
      property_type
      user_id 1
   end
end

或者您可以在测试数据库中保留一个 id 为 1 的 property_type 记录。

【讨论】:

  • Zhong,我已经做出了您建议的更改,解决了最初显示的错误,但现在还有其他错误。这是我到目前为止所做的。 --更新了属性工厂以使用关联。 --更新了属性类型工厂以使用关联。 --更新的属性模型有'belongs_to:user'参考。失败:1) 属性创建修改已成功完成失败/错误:@property = current_user.properties.find(params[:id]) ActiveRecord::RecordNotFound: Couldn't find Property with 'id'=3 [WHERE "properties "."user_id" = ?]
  • 如何创建房产记录? current_user.properties.create?或Properties.new。我觉得属性记录没有user_id。
  • current_user.properties.create 将为current_user 创建属性
  • 钟。问题是保存属性记录时的 user_id 为 4。但是,应该绑定到记录的 user_id 是 3。ID 序列未重置是有问题的。
  • 因为@property = FactoryGirl.create(:property) 将使用新用户创建一个新属性(假设您在属性工厂中定义了用户关联)。一种更易读的方法是 @user.properties.create(FactoryGirl.attributes_for(:property)) 。两者都意味着这些属性属于@user。
猜你喜欢
  • 2017-03-04
  • 2020-09-07
  • 2016-08-13
  • 1970-01-01
  • 2016-06-28
  • 2018-10-13
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多