简体   繁体   English

带有transactional_fixtures = true的Rspec引发唯一性错误

[英]Rspec with transactional_fixtures=true throws uniqueness errors

I'm testing my API, build with Grape and Rails, with RSpec and get a lot of uniqueness validation errors. 我正在测试我的API,使用Grape和Rails以及RSpec进行构建,并且遇到很多唯一性验证错误。

I'm using config.use_transactional_fixtures = true to rollback the database after each test, but I'm getting this errors: 我在每次测试后使用config.use_transactional_fixtures = true来回滚数据库,但出现此错误:

  7) API GET /api/v1/quotations returns 200 when there is at least one quotation
     Failure/Error: FactoryGirl.create(:quotation)
     ActiveRecord::RecordInvalid:
       Validation failed: Number has already been taken
     # ./spec/requests/api/quotations_spec.rb:56:in `block (3 levels) in <top (required)>'

I think the problem is, that my models have transitive dependencies: 我认为问题是我的模型具有传递依赖项:

Clients have Contacts and Contacts have Quotations. ClientsContactsContacts有报价。 So when creating a quotation, a corresponding contact with a corresponding client should be created. 因此,在创建报价时,应创建与相应客户的相应联系人。 And a quotation always belongs to a Request . 引号始终属于Request But it seems, that FactoryGirl doesn't create new instances? 但是似乎FactoryGirl不会创建新实例吗?

The validations error does not belong to a quotation. 验证错误属于引号。 If I remove the uniqueness validation on the quotation model, I get the same error. 如果删除报价模型上的唯一性验证,则会收到相同的错误。 Actually, it belongs to the client model. 实际上,它属于客户端模型。

It seems, that not all tables get truncated? 似乎不是所有表都被截断了吗? I event tried out DatabaseCleaner gem, but get the same errors (disabled use_transactional_fixtures before tried DatabaseCleaner). 我事件尝试了DatabaseCleaner gem,但是得到了相同的错误(在尝试DatabaseCleaner之前禁用了use_transactional_fixtures )。

Note: I'm using Postgres and the apartment gem for multi-tenancy. 注意:我正在使用Postgres和apartment gem进行多租户。

That are my factories: 那是我的工厂:

Client factory 客户工厂

FactoryGirl.define do

  factory :client do
    number Faker::Number.number(8)
    company Faker::Company.name
    address1 Faker::Address.street_address
    address2 Faker::Address.secondary_address
    city Faker::Address.city
    zip Faker::Address.zip
    country Faker::Address.country
    tax '19'
    email Faker::Internet.email
    phone Faker::PhoneNumber.phone_number
    web Faker::Internet.url
  end

end

Contact factory 联系工厂

FactoryGirl.define do

  factory :contact do
    title Faker::Name.title
    name Faker::Name.name
    surname Faker::Name.last_name
    department Faker::Commerce.department
    email Faker::Internet.email
    phone Faker::PhoneNumber.phone_number
    password 'secret'
    password_confirmation 'secret'
    client
  end

end

Quotation factory 报价厂

FactoryGirl.define do

  factory :quotation do
    number Faker::Number.number(8)
    title Faker::Lorem.word
    payable Faker::Lorem.sentence
    request
    contact
  end

end

Request factory 要求工厂

FactoryGirl.define do

  factory :request do
    number Faker::Number.number(8)
    title Faker::Lorem.word
    content Faker::Lorem.sentence
    contact
  end

end

Part of my quotations_spec.rb 我的quotations_spec.rb

require 'spec_helper'

describe API do

  include Rack::Test::Methods

  def app
    API
  end

  ####################################################################################################################
  # Authentication
  ####################################################################################################################

  let(:url) { 'http://testing.domain.com' }
  let!(:access_token) do
    user = FactoryGirl.create(:user)
    api_key = FactoryGirl.create(:api_key_session, foreign_id: user.id)
    api_key.access_token
  end

  describe 'GET /api/v1/quotations' do

    it 'returns 401 when unauthorized' do

      get "#{url}/api/v1/quotations"
      expect(last_response.status).to eq 401

    end

  end

  ####################################################################################################################
  # GET quotations
  ####################################################################################################################

  describe 'GET /api/v1/quotations' do

    #----------------------------------------------------------------------------------------------------------------#


    it 'returns 404 when quotations not found' do

      header 'X-Access-Key', access_token
      get "#{url}/api/v1/quotations"

      expect(last_response.status).to eq 404

    end

    #----------------------------------------------------------------------------------------------------------------#

    it 'returns 200 when there is at least one quotation' do

      FactoryGirl.create(:quotation)

      header 'X-Access-Key', access_token
      get "#{url}/api/v1/quotations"

      expect(last_response.status).to eq 200

    end

    #----------------------------------------------------------------------------------------------------------------#

  end

end

Update 1 更新1

I switched to DatabaseCleaner and tried to debug this: 我切换到DatabaseCleaner并尝试调试它:

config.after(:each) do

    puts
    puts '####'
    puts Client.all
    puts '####'
    puts Contact.all
    puts '####'
    puts

    DatabaseCleaner.clean

    puts
    puts '####'
    puts Client.all
    puts '####'
    puts Contact.all
    puts '####'
    puts

    # Reset tentant back to `public`
    Apartment::Database.reset

  end

Actually, the database gets cleaned, so Contact.all and Client.all is empty after Database.clean . 实际上,数据库已清除,因此在Database.clean之后, Contact.allClient.all为空。 This is confusing, because otherwise the validation errors shouldn't occur? 这令人困惑,因为否则不应该发生验证错误?

I figured it out. 我想到了。 Thanks to this answer: https://stackoverflow.com/a/16726614/1184904 感谢这个答案: https : //stackoverflow.com/a/16726614/1184904

I have to replace the unique fields with sequences like this: 我必须用以下序列替换唯一字段:

FactoryGirl.define do

  factory :user do
    name Faker::Name.name
    surname Faker::Name.last_name
    sequence :email do |n|
      "foo#{n}@bar.de"
    end
    password 'secret'
    password_confirmation 'secret'
  end

end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 FactoryGirl HABTM transactional_fixtures产生MissingAttributeError - FactoryGirl HABTM transactional_fixtures produce MissingAttributeError 一个人如何使用Test :: Unit在一组测试中切换对transactional_fixtures的使用? - How can a person toggle the use of transactional_fixtures for one set of tests using Test::Unit? 使用 RSpec 2 关闭一个规格的交易固定装置 - Turn off transactional fixtures for one spec with RSpec 2 在Rspec中禁用事务处理夹具无效 - disabling transactional fixtures in Rspec has no effect RSpec-共享的数据库连接 和交易装置不起作用 - RSpec - shared DB conn. & transactional fixtures not working Rspec:事务夹具在升级到rails 4后不起作用 - Rspec: Transactional fixtures do not work after upgrading to rails 4 Rails 3和Rspec 2关闭各个测试的事务夹具 - Rails 3 and Rspec 2 turn off transactional fixtures for individual tests RSpec 中的固定装置 - Fixtures in RSpec Rspec validates_uniqueness_of测试失败,并带有其他验证错误 - Rspec validates_uniqueness_of test failing with additional validation errors Selenium Chrome在Rails Rspec Docker环境中启用事务处理夹具后看不到数据库更改 - Selenium Chrome not seeing database changes with transactional fixtures enabled in Rails Rspec Docker environment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM