如何使用Factory Girl生成回形针附件?


119

我的模型人有很多图像,其中图像有一个名为data的回形针附件字段,缩写形式显示在下面:

class Person
  has_many :images
  ...
end

class Image
  has_attached_file :data
  belongs_to :person
  ...
end

人员必须至少附有一张图像。

使用FactoryGirl时,我的代码类似于以下内容:

Factory.define :image do |a|
  a.data { File.new(File.join(Rails.root, 'features', 'support', 'file.png')) }
  a.association :person
end

Factory.define :person do |p|
  p.first_name 'Keyzer'
  p.last_name 'Soze'
  p.after_create do |person|
    person.assets = [Factory.build(:image, :person => person)]
  end
  # p.images {|images| [images.association(:image)]}
end

(注意,我也尝试过上面注释掉的代码,也尝试过)大多数情况下,当我运行黄瓜功能时,都会出现类似于以下内容的错误:

没有这样的文件或目录-/tmp/stream,9887,0.png(Errno :: ENOENT)

...

有时测试会成功运行。

谁能告诉我我在这里遇到了什么问题,或者他们如何一起使用FactoryGirl和Paperclip来实现我想要实现的目标?

我正在使用Rails 3。


2
只需使用Keyzer Soze作为测试名称就可以投票表决!
布雷诺2014年

当我这样做时,每次运行测试套件时,都会生成照片并将其放置在public / system文件夹中。测试套件运行完毕后,照片不会被销毁。还有其他人注意到吗?
Jwan622 '16

Answers:


86

您可以使用fixture_file_upload

include ActionDispatch::TestProcess 在您的测试助手中,这是一个示例工厂:

include ActionDispatch::TestProcess

FactoryBot.define do
  factory :user do
    avatar { fixture_file_upload(Rails.root.join('spec', 'photos', 'test.png'), 'image/png') }
  end
end

在以上示例中, spec/photos/test.png在运行测试之前需要存在于应用程序的根目录中。

请注意,这FactoryBot是的新名称FactoryGirl


2
这个答案是完全正确的,但是可以更清楚地说,TestProcess include需要包含在Factory中,而不仅仅是在spec_helper中。
安德鲁·哈伯斯

2
感谢您的澄清,安德鲁。您可能还必须在FactoryGirl.define块之前放置“ include ActionDispatch :: TestProcess”(这不是本要点:gist.github.com/313121)。
山姆

3
另外,{ }是必填项。没有它,它会破裂
bigpotato

3
进一步的澄清:将include ActionDispatch::TestProcess应该在出厂文件的最上面插入,FactoryGirl.define do...end块。
Frank Koehl 2014年

49

较新的FG语法,无需添加任何内容

factory :user do
  avatar { File.new(Rails.root.join('app', 'assets', 'images', 'rails.png')) }
end

或者,更好的是

factory :user do
  avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") } 
end

2
我喜欢它,但请记住Rails 4会删除app / assets / images / rails.png,因此您需要考虑这一更改:)
stephenmurdoch

38

Pivotal Labs的Desmond Bowe 建议避免由于内存泄漏问题而导致fix_file_upload。相反,您应该直接在工厂中设置回形针字段:

factory :attachment do
  supporting_documentation_file_name { 'test.pdf' }
  supporting_documentation_content_type { 'application/pdf' }
  supporting_documentation_file_size { 1024 }
  # ...
end

为我工作。也很简单,不需要spec / test文件夹中的现有文件。
bibstha 2014年

2
除了避免内存泄漏之外,这种方式还可以加快测试速度。
evedovelli

提到的博客文章移至ivotal.io/blog
Karsten S.

不幸的是,这不适用于上的附件验证content_type。为此,您需要一个有效的文件对象。
卡尔斯滕S.17年



4

尝试使用ActionController :: TestUploadedFile。您只需将file属性设置为TestUploadedFile的实例,其余的回形针就可以了。例如

valid_file = File.new(File.join(Rails.root, 'features', 'support', 'file.png'))  
p.images { 
   [
     ActionController::TestUploadedFile.new(valid_file, Mime::Type.new('application/png'))
   ] 
}

0

在某些情况下,上述答案可能会有所帮助,而在我的一种情况下,上述答案实际上是有帮助的,但是当使用Carrierwave时,此问题的先前解决方案这次并没有解决。

第一步:

对我来说,为我添加after :create解决的问题是这样的:

after :create do |b|
  b.update_column(:video_file, File.join(Rails.root, 'spec', 'fixtures', 'sample.mp4'))
end

设置内嵌视频文件,例如 video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }不能解决问题,并且报告了错误。

第二种方法:

定义一个这样的工厂(更改personal_file为附件名称):

FactoryGirl.define do
  factory :contact do
    personal_file { File.new("#{Rails.root}/spec/fixtures/personal_files/my_test_file.csv") }
    personal_file_content_type 'text/csv'

  end
end

并将这些行添加到config/environemnts/test.rb

config.paperclip_defaults = {
  url: "#{Rails.root}/spec/fixtures/:attachment/:filename",
  use_timestamp: false
}

-1

您到底要测试什么?那个回形针会成功附加文件吗?这确实看起来像回形针应该处理的测试,而不是您的应用程序。

你有没有尝试过

a.data { File.join(Rails.root, 'features', 'support', 'file.png') }

我们使用机械师而不是factory_girl,并且只使用了类似

Image.blueprint do
  image { RAILS_ROOT + 'spec/fixtures/images/001.jpg' }
end

虽然,当执行此操作时,我们并没有进行太多测试,我们通常只想拥有一个有效的Image对象。


我的模型需要与启用了Paperclip的模型进行有效关联,而该模型本身具有有效的附件。
埃里克(Eric)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.