#ruby-on-rails #ruby #rspec
#ruby-on-rails #ruby #rspec
Вопрос:
У меня есть модель Trip, которая устанавливает значение по умолчанию для ‘refund_policy’ на ‘refund_policy’ компании этой поездки. Компания сама по себе имеет значение по умолчанию для ‘refund_policy’ в соответствии с политикой компании с идентификатором 4.
Мои тесты на наличие допустимой фабрики для Trip завершаются неудачей, как и многие другие, потому что в базе данных нет компании с идентификатором 4. Я попытался указать компанию с явным идентификатором. Кроме того, мои попытки заблокировать эту компанию или ее политику возврата пока не сработали.
Все используемые фабрики действительны, как определено предыдущими тестами.
Я пытался:
#trip_spec.rb
describe Trip do
let(:company) { FactoryGirl.build(:company) }
let(:refund_policy) { 'example refund policy' }
before do
company.stub(:refund_policy).and_return(refund_policy)
Company.stub(:find).and_return(company)
end
it "has a valid factory" do
expect( FactoryGirl.build :trip, company_id: company.id ).to be_valid
end
end
Я также пытался:
let(:company) { FactoryGirl.build(:company, id: 4) }
it "has a valid factory" do
expect( FactoryGirl.build :trip ).to be_valid
end
А также:
let!(:company) { FactoryGirl.create(:company, id: 4) }
it "has a valid factory" do
expect( FactoryGirl.build :trip ).to be_valid
end
Все это приводит к этому сообщению об ошибке
# gives this error
Trip has a valid factory
Failure/Error: let(:company) { FactoryGirl.build(:company) }
ActiveRecord::RecordNotFound:
Couldn't find Company with id=4
# ./app/models/company.rb:70:in `default_refund_policy'
# ./app/models/company.rb:66:in `set_defaults'
# ./spec/models/trip_spec.rb:5:in `block (2 levels) in <top (required)>'
Значение по умолчанию для политики возврата за поездку
#trip.rb
def set_defaults
self.refund_policy = company.refund_policy if company amp;amp; (refund_policy.blank? || (refund_policy amp;amp; refund_policy.strip.length == 0))
end
Значение по умолчанию для политики возврата компании
#company.rb
def set_defaults
self.refund_policy = default_refund_policy if refund_policy.blank? || (refund_policy amp;amp; refund_policy.strip.length == 0)
end
def default_refund_policy
Company.find(4).refund_policy
end
Как я могу эффективно учитывать этот путь значений по умолчанию?
Заранее спасибо.
Комментарии:
1. Можете ли вы попробовать
let!(:company) { FactoryGirl.create(:company, id: 4) }
2. Только что попробовал. Изменений нет.
Ответ №1:
Все три завершаются ошибкой, потому что set_defaults
вызывается как часть процесса сборки, который по очереди вызывает, default_return_policy
который по очереди вызывает find
. При существующем рабочем коде вам потребуется заглушка Company.find
перед попыткой создания компании.
Кроме того:
- Ваш второй пример не сработал бы, потому что вы используете
build
вместоcreate
- Ваш третий пример не сработал бы, потому что вы используете
let
вместоlet!
и не ссылаетесь на переменную в вашем примере.
Следующее должно, по крайней мере, приблизить вас:
describe Trip do
before do
company = InstanceDouble(Company, refund_policy: 'example refund policy')
Company.stub(:find).and_return(company)
end
it "has a valid factory" do
expect( FactoryGirl.build :trip, company_id: company.id ).to be_valid
end
end
Комментарии:
1. Я думаю, проблема в том, что мне нужна компания с идентификатором 4, прежде чем я смогу даже создать новую компанию.
2. Да, это было началом правильного пути, спасибо. Я переключил ‘InstanceDouble’ на просто ‘double’, присвоил ему идентификатор 4 и политику возврата, и вуаля!
3. Я также обновил ваш метод заглушки до текущего синтаксиса: разрешить (Company).получать(:find).and_return(company)