Wie erstelle ich mit Factory Girl einen Büroklammer-Anhang?

119

Ich habe Modell Person, die viele Bilder hat, wobei Bilder ein Büroklammer-Anhangsfeld namens Daten haben, eine abgekürzte Version, die unten angezeigt wird:

class Person
  has_many :images
  ...
end

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

Der Person muss mindestens ein Bild beigefügt sein.

Bei der Verwendung von FactoryGirl habe ich folgenden Code:

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

(Hinweis: Ich habe auch versucht, dass der oben auskommentierte Code ebenfalls ausprobiert wurde.) Die meiste Zeit, wenn ich Gurkenfunktionen ausführe, wird eine Fehlermeldung angezeigt, die der folgenden ähnelt:

Keine solche Datei oder kein solches Verzeichnis - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Manchmal laufen die Tests erfolgreich.

Kann mir jemand sagen, was das Problem ist, das ich hier habe, oder wie sie FactoryGirl und Paperclip zusammen verwenden, um so etwas wie das zu erreichen, was ich erreichen möchte?

Ich benutze Rails 3.

Laz
quelle
2
Stimmen Sie über die Frage ab, nur weil Sie Keyzer Soze als Testnamen verwenden!
Breno
Wenn ich das mache ... werden Fotos generiert und jedes Mal, wenn ich die Testsuite ausführe, in den Ordner public / system gelegt. Die Fotos werden nicht zerstört, nachdem die Testsuite ausgeführt wurde. Hat das noch jemand bemerkt?
Jwan622

Antworten:

86

Sie können fixture_file_upload verwenden

include ActionDispatch::TestProcess In Ihrem Testhelfer finden Sie hier eine Beispielfabrik:

include ActionDispatch::TestProcess

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

Im obigen Beispiel spec/photos/test.pngmuss es im Stammverzeichnis Ihrer Anwendung vorhanden sein, bevor Sie Ihre Tests ausführen.

Beachten Sie , dass FactoryBotein neuer Name für ist FactoryGirl.

DanS
quelle
2
Diese Antwort ist völlig richtig, aber es ist möglicherweise klarer zu sagen, dass das TestProcess-Include in der Factory enthalten sein muss und nicht nur in Ihrem spec_helper.
Andrew Hubbs
2
Danke für die Klarstellung, Andrew. Möglicherweise müssen Sie auch "include ActionDispatch :: TestProcess" vor dem FactoryGirl.define-Block platzieren (was in diesem Gist nicht der Fall ist: gist.github.com/313121 ).
Sam
3
Auch die { }sind erforderlich. Es bricht ohne es
Bigpotato
3
Weitere Klarstellung: Die include ActionDispatch::TestProcesssollte ganz oben in der Factory-Datei außerhalb des FactoryGirl.define do...endBlocks eingefügt werden .
Frank Koehl
49

Neuere FG-Syntax und keine Includes erforderlich

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

oder noch besser,

factory :user do
  avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") } 
end
Neal
quelle
2
Ich mag es, aber denken Sie daran, dass Rails 4 App / Assets / Images / Rails.png entfernt, so dass Sie diese Änderung berücksichtigen müssen :)
stephenmurdoch
38

Desmond Bowe von Pivotal Labs schlägt vor, fixture_file_upload aufgrund von Speicherverlustproblemen zu vermeiden. Stattdessen sollten Sie die Büroklammerfelder direkt in Ihrer Fabrik einstellen:

factory :attachment do
  supporting_documentation_file_name { 'test.pdf' }
  supporting_documentation_content_type { 'application/pdf' }
  supporting_documentation_file_size { 1024 }
  # ...
end
Rick Quantz
quelle
Funktioniert bei mir. Auch einfach genug, um keine vorhandene Datei im Ordner spec / test zu benötigen.
Bibstha
2
Auf diese Weise werden nicht nur Speicherlecks vermieden, sondern die Tests werden auch schneller.
Evedovelli
Der erwähnte Blog-Beitrag wurde auf pivotal.io/blog verschoben
Karsten S.
Leider funktioniert dies bei aktivierter Anhangsüberprüfung nicht content_type. Dafür benötigen Sie ein gültiges Dateiobjekt.
Karsten S.
25

Ich habe den folgenden Code verwendet:

Schienen 2

http://gist.github.com/162881

Schienen 3

https://gist.github.com/313121

deb
quelle
1
Ich frage mich nur die gleichen Dinge und das funktioniert wunderbar. Vielen Dank. Ich habe es in einen Initialisierer gesteckt.
Todd
1
Beachten Sie Folgendes: Im Folgenden wird die ältere FactoryGirl-Syntax verwendet. DanS Answer verwendet die neue Syntax.
Andrew Hubbs
12
file { File.new(Rails.root.join('spec', 'fixtures', 'filename.png')) }
Matthew Deiters
quelle
Dies ist die einfachste funktionale Lösung.
Superluminary
4

Versuchen Sie es mit ActionController :: TestUploadedFile. Sie können die Dateieigenschaft einfach auf eine Instanz von TestUploadedFile setzen, und die Büroklammer sollte sich um den Rest kümmern. Beispielsweise

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

Die obigen Antworten können in einigen Fällen helfen, und die Antwort hat tatsächlich in einer meiner Situationen geholfen, aber bei Verwendung einer Carrierwave hat die vorherige Lösung aus dieser Frage diesmal nicht funktioniert.

ERSTE ANSATZ:

Für mich hat das Hinzufügen eines after :createdas Problem für mich folgendermaßen gelöst:

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

Das Einstellen der Inline-Videodatei video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }hat nicht funktioniert und es wurden Fehler gemeldet.

ZWEITER ANSATZ:

Definieren Sie eine Fabrik wie diese (ändern Sie personal_fileIhren Anhangsnamen):

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

Und fügen Sie diese Zeilen hinzu zu config/environemnts/test.rb:

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

Was testest du genau? Diese Büroklammer wird die Datei erfolgreich anhängen? Das scheint wirklich ein Test zu sein, den eine Büroklammer durchführen sollte, nicht Ihre Bewerbung.

Hast du es versucht

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

Wir verwenden Machinist anstelle von factory_girl und haben gerade Dinge wie verwendet

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

Obwohl wir dabei nicht wirklich viel testen, möchten wir normalerweise nur ein gültiges ImageObjekt haben.

theIV
quelle
Ich habe Modelle, die eine gültige Zuordnung zu einem Büroklammer-fähigen Modell erfordern, selbst mit einem gültigen Anhang.
Eric