我正在测试我的 API,使用 Grape 和 Rails 构建,使用 RSpec 并得到很多唯一性验证错误。
每次测试后我都使用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)>'
我认为问题在于,我的模型具有传递依赖关系:
Clients
有Contacts
和Contacts
有报价。因此,在创建报价单时,应创建与相应客户的相应联系人。并且引文总是属于 a Request
。但看起来,FactoryGirl 没有创建新实例?
验证错误不属于引用。如果我删除报价模型上的唯一性验证,我会得到同样的错误。实际上,它属于客户端模型。
似乎并非所有表都被截断?我尝试了 DatabaseCleaner gem,但得到了相同的错误(use_transactional_fixtures
在尝试 DatabaseCleaner 之前被禁用)。
注意:我正在使用 Postgres 和公寓 gem 进行多租户。
那是我的工厂:
客户工厂
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
联系工厂
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
报价厂
FactoryGirl.define do
factory :quotation do
number Faker::Number.number(8)
title Faker::Lorem.word
payable Faker::Lorem.sentence
request
contact
end
end
请求工厂
FactoryGirl.define do
factory :request do
number Faker::Number.number(8)
title Faker::Lorem.word
content Faker::Lorem.sentence
contact
end
end
我的一部分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
更新 1
我切换到 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
实际上,数据库被清理了,所以.Contact.all
之后Client.all
是空的Database.clean
。这很令人困惑,因为否则不应该发生验证错误?