我有一对多关系的模型,他们是民意调查和选择。
如何正确测试它们,因为下面的代码导致ActiveRecord::RecordInvalid:
。我想在旅途中创建父级(Poll
)及其子级(Choices
),而不是先创建父级(Poll
),然后保存子级(Choices
) 之后。
以下是代码:
首先,我得到的所有测试用例的错误:
Failure/Error: @poll = FactoryGirl.build(:poll_with_choices, user: @user)
ActiveRecord::RecordInvalid:
Validation failed: Choices choices required at least 2
民意调查模式:
class Poll < ActiveRecord::Base
belongs_to :user
has_many :choices
accepts_nested_attributes_for :choices
validates :title, presence: true
validates_each :choices do |record, attr, value|
record.errors.add attr, "choices required at least 2" if record.choices.length < 2
end
end
投票工厂:
FactoryGirl.define do
factory :poll do
title { FFaker::Lorem.phrase }
description { FFaker::Lorem.sentences }
user
factory :poll_with_choices do
transient do
choices_count 3
end
after(:build) do |poll, evaluator|
build_list(:choice, evaluator.choices_count)
end
end
end
end
选择工厂:
FactoryGirl.define do
factory :choice do
label { FFaker::Name.name }
votes 0
poll
end
end
投票规范
require 'rails_helper'
RSpec.describe Poll, type: :model do
before do
@user = FactoryGirl.create(:user)
@poll = FactoryGirl.build(:poll_with_choices, user: @user)
end
subject { @poll }
it { should respond_to(:title) }
it { should respond_to(:description) }
it { should validate_presence_of(:title) }
it { should belong_to(:user) }
it { should have_many(:choices) }
it { should accept_nested_attributes_for(:choices) }
describe "#save" do
before do
@user = FactoryGirl.create(:user)
end
it "success" do
poll = FactoryGirl.build(:poll_with_choices, user: @user)
expect(poll.save).to eql true
end
it "fail" do
poll = FactoryGirl.build(:poll, user: @user)
poll.choices = FactoryGirl.build_list(:choice, 1)
expect(poll.save).to eql false
end
end
end
作为FactoryGirl.create
的参考,不 FactoryGirl.build
:http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Associations
提前谢谢。
答案 0 :(得分:3)
最后,我使用FactoryGirl trait和attributes
以下是poll
工厂代码:
FactoryGirl.define do
factory :poll do
title { FFaker::Lorem.phrase }
description { FFaker::Lorem.sentences }
user
choices_attributes { [FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice)] }
trait :with_many_choices do
choices_attributes { [
FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice),
FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice),
FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice)
] }
end
trait :with_invalid_choices do
choices_attributes { [FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice), FactoryGirl.attributes_for(:choice, label: '')] }
end
trait :with_lack_of_choices do
choices_attributes { [FactoryGirl.attributes_for(:choice)] }
end
trait :without_choices do
choices_attributes { [] }
end
end
end
参考文献(感谢):
答案 1 :(得分:0)
如果我看得正确你的工厂有错误:
FactoryGirl.define do
factory :poll do
title { FFaker::Lorem.phrase }
description { FFaker::Lorem.sentences }
user
factory :poll_with_choices do
transient do
choices_count 3
end
after(:build) do |poll, evaluator|
build_list(:choice, evaluator.choices_count, poll: poll)
end
end
end
end
您需要将您的民意调查分配给选择,否则选择工厂将为每个选择创建民意调查。
答案 2 :(得分:0)
这就是我在我的案例中所做的:
FactoryBot.define do
factory :store do
sequence(:name) { |n| "Store #{n}" }
association :user
sellers_attributes [ FactoryBot.attributes_for(:seller) ]
end
end
我必须重构我的测试并重命名一些事情。