0

I'm testing a CSV uploader with rspec and I've saved a test file in /spec/fixtures that I pull into my tests with fixture_file_upload:

let(:file) do
  fixture_file_upload(
    Rails.root.join("spec/fixtures/chargeback_test.csv"),
    "text/csv"
  )
end

This works but I have the file path in each spec. I'd like to DRY out my code by putting this in a factory but I'm having trouble making FactoryGirl understand that I want a Tempfile back from FactoryGirl.create(:chargeback_csv).

I would have guessed the factory should look like this:

include ActionDispatch::TestProcess

FactoryGirl.define do
  factory :chargeback_csv, :class => "Tempfile" do
    ignore do
      path      { Rails.root.join("spec/fixtures/chargeback_test.csv") }
      mime_type { "text/csv" }
      binary    { false }
    end

    initialize_with { fixture_file_upload(path, mime_type, binary) }

  end
end

But, using this in my specs results in the following error:

Failure/Error: let(:file) { FactoryGirl.create(:chargeback_csv) }
NoMethodError:
  undefined method `save!' for #<Tempfile:0x112fec730>

Solved! The save! error is caused because FactoryGirl calls to_create on new objects that it creates. Newer versions of FactoryGirl have an option skip_create to avoid this error. I'm on an old version so I added to_create {} to the factory and all my tests are green again.

include ActionDispatch::TestProcess

FactoryGirl.define do
  factory :chargeback_csv, :class => "Tempfile" do

    to_create {}

    ignore do
      path      { Rails.root.join("spec/fixtures/chargeback_test.csv") }
      mime_type { "text/csv" }
      binary    { false }
    end

    initialize_with { fixture_file_upload(path, mime_type, binary) }

  end
end
user341493
  • 414
  • 1
  • 7
  • 15

1 Answers1

2

Check out https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#custom-construction. I need to run now, but 'll update this answer with specifics for your situation in a couple of hours if you haven't already figured it out.

Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • I thought `initialize_with` looked promising. I'm still having trouble with this so any additional help would be greatly appreciated. I'm going to update my question with the latest factory I'm trying and the errors I'm getting. – user341493 Sep 17 '13 at 16:34
  • Got it :) The error about `save!` is happening because `to_create()` calls `save!` on the object the factory creates. Newer versions of FactoryGirl have `skip_create` to deal with this but I had to define `to_create` as an empty block for this to work with my version. – user341493 Sep 17 '13 at 16:46
  • Impressive piece of investigative work! How'd you figure that out? Also, my reading of the link I shared suggests that you don't need the `ignore` block since you're referencing all the arguments in your `initialize_block`. Your way is probably clearer, but I was just curious if you read it that way and wanted to try it. – Peter Alfvin Sep 17 '13 at 17:00