我有以下工厂设置
FactoryGirl.define do
factory :image do
title 'Test Title'
description 'Test Description'
photo File.new("#{Rails.root}/spec/fixtures/louvre_under_2mb.jpg")
after(:build) do
FactoryGirl.build_list(:category, 1)
end
end
end
在我的模型中,我有这些验证
class Image < ActiveRecord::Base
has_many :categories
validates :title, presence: { message: "Don't forget to add a title" }
validates :description, presence: { message: "Don't forget to add a description" }
validates :categories, presence: { message: 'Choose At Least 1 Category' }
end
当我运行此测试时,它失败
RSpec.describe Image, type: :model do
it 'should have a valid Factory' do
expect(FactoryGirl.build(:image)).to be_valid
end
end
Failure/Error: expect(FactoryGirl.build(:image)).to be_valid
expected #<Image id: nil, title: "Test Title", description: "Test Description", photo_file_name: "louvre_under_2mb.jpg", photo_content_type: "image/jpeg", photo_file_size: 65618, photo_updated_at: "2015-12-15 08:01:07", created_at: nil, updated_at: nil> to be valid, but got errors: Categories Choose At Least 1 Category
我是否接近这个错误,因为我认为在整个对象创建之前验证不会启动?还是我错误地想到了这个?
由于
答案 0 :(得分:2)
问题出在这一部分。
after(:build) do
FactoryGirl.build_list(:category, 1)
end
这将创建大小为1的类别列表,但这些类别不与图像对象相关联。正确的方法如下:
transient do
categories_count 1
end
after(:build) do |image, evaluator|
image.categories = build_list(:category, evaluator.categories_count)
end
或
transient do
categories_count 1
end
categories { build_list(:category, categories_count) }
就个人而言,我会选择最后一个选项。
photo
属性也是有问题的。 FactoryGirl是关于创建记录的灵活性。但是您使用它的方式不会提供任何灵活性,因此照片属性将在您使用此工厂创建的所有记录之间共享。你迟早会面临一些麻烦。
因此,创建photo
属性的正确方法如下:
transient do
photo_name 'default_photo.jpg'
end
photo { File.new(File.join(Rail.root, "spec/fixtures", photo_name) }
比你可以这样使用
FactoryGirl.build(:image, photo_name: 'new_photo_name.jpg')
答案 1 :(得分:0)
我建议不要在图片工厂中使用after
方法。您应该创建正确的关联。使用此功能,您将解决验证错误,并且将来不会遇到其他问题。
class Image
accepts_nested_attributes_for :categories
end
FactoryGirl.define do
factory :image do
categories_attributes { [FactoryGirl.attributes_for(:category)] }
end
end