Carrierwave: How to attach files in tests

Updated . Posted . Visible to the public.

Attaching files to a field that is handled by Carrierwave uploaders (or maybe any other attachment solution for Rails) in tests allows different approaches. Here is a short summary of the most common methods.

You might also be interested in this card if you see the following error in your test environment:

CarrierWave::FormNotMultipart:
You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.
If this is a file upload, please check that your upload form is multipart encoded.

Factory Bot

FactoryBot.define do

  factory :user do
    name { 'Bruce' }
    email { 'bruce@wayne.us' }
    avatar { Rack::Test::UploadedFile.new('spec/fixtures/files/avatar.jpg') }
  end

end

Note that if the avatar is an optional field, you want to move the file assignment to an optional trait.

FactoryBot.define do

  factory :user do
    name { 'Bruce' }
    email { 'bruce@wayne.us' }
  
    trait :with_avatar do
      avatar { Rack::Test::UploadedFile.new('spec/fixtures/avatar.jpg') }
    end  
  end
end

Storing a file attribute takes a few milliseconds, as CarrierWave needs to write out a file, compute versions, etc. You are going to create a lot of users in your E2E tests, and you won't need avatars for all of them:

RSpec

RSpec has a helper method file_fixture Show archive.org snapshot :

describe User do

  let(:user) { build(:user, attachment: file_fixture('avatar.jpg').open) }

end

You can configure the directory where RSpec looks for fixture files:

RSpec.configure do |config|
  config.file_fixture_path = "spec/custom_directory"
end

Alternatives:

  • Rails.root.join('spec/fixtures/files/avatar.jpg').open('r')
  • Rails.root.join('spec/fixtures/files/avatar.jpg').read
  • File.open('spec/fixtures/files/avatar.jpg') (might only work if you run the command from the Rails root directory)

Cucumber

When('I attach the file {string} to {string}') do |path, field|
  attach_file(field, Rails.root.join('spec', 'fixtures', path))
end

Alternatives

Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Emanuel to makandra dev (2022-01-13 08:43)