我正在使用fixture来在Ruby on Rails项目上加载测试数据。我搬到了Factory Girl,但我收到了重复的协会条目。
我有Group
模型和Value
模型。 Group
可以有多个Values
。
另外,我正在使用Cucumber进行测试。并FactoryGirl.lint
填充数据库。
groups.yml
group_1:
name: "Flavour"
values.yml
value_1:
name: "Strawberry"
group: group_1
value_2:
name: "Mint"
group: group_1
value_3:
name: "Chocolate"
group: group_1
这很好用。创建一个Group
并将3 Values
附加到其上。
groups.rb
FactoryGirl.define do
factory :group do
name "Flavour"
end
end
values.rb
FactoryGirl.define do
factory :value_1, class: :value do
name "Strawberry"
group
end
factory :value_2, class: :value do
name "Mint"
group
end
factory :value_3, class: :value do
name "Chocolate"
group
end
end
这不起作用。 Factory Girl正在创建3 Groups
,每个{1}与1 Value
相关联。
这是Factory Girl的正常行为吗?
另外,我读到use_transactional_fixtures
应该设置为true。情况已经如此。
答案 0 :(得分:2)
您的价值工厂被告知要将集团工厂用于他们的集团,并且集团工厂被告知要创建一个名为' Flavor'的新集团。您想要做的不同的是,您希望集团工厂返回现有的' Flavor'而不是一个新的。这是如何做到的。
FactoryGirl.define do
factory :group, class: :group do
name 'Flavor'
initialize_with {Group.find_or_initialize_by(name: name)}
end
end
即如果您已经拥有所需名称的组,请使用现有组。如上所述,以便有一个默认名称,你得到相同的'使用现有的如果存在'传递替代名称时的行为。
答案 1 :(得分:2)
我不认为你真的已经掌握了使用固定装置和工厂之间的概念差异。
database_cleaner
之类的工具清除测试之间的任何残留状态。你什么也没做就开始了。 FactoryGirl.lint
不会填充数据库。它是一个检查您的工厂定义是否正确的linter。
如果你只是用它创建一堆灯具,那么使用factory_girl绝对没有意义。所以你想要做的事情是:
FactoryGirl.define do
factory :value do
name { ["Strawberry", "Mint", "Chocolate"].sample }
group
end
end
从固定装置到工厂的一个心理障碍是你必须停止编写测试,就像你在哪里使用夹具数据一样:
describe "GET /users/:id" do
let!(:user){ FactoryGirl.create(:user) }
let(:json) { JSON.parse(response.body) }
before { get users_path(@user), format: :json }
it "has the correct name" do
# bad
expect(json["name"]).to eq "John Doe" # strong coupling to factory!
# good
expect(json["name"]).to eq user.name # we don't know what the factory generates.
end
end
如果必须进行测试,必须知道某个工厂值,或者工厂需要与某个对象相关联,那么请明确地进行测试,而不要弄乱你的定义。
let(:user) { FactoryGirl.create(:user, name: 'Max') }
let(:item) { user.items.create(FactoryGirl.attributes_for(:item)) }
it "has an awesome name" do
expect(user.name).to eq 'Max'
end
it "is associated" do
expect(item.user).to eq user
end