ruby-on-railsrspecrails-activestorage

How to solve ActiveStorage::FileNotFoundError: when running tests with rspec?


I'm getting a file not found error using ActiveStorage when running rspec and I don't know what's wrong. This is how it's setup.

storage.yml

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

config/environments/test.rb

config.active_storage.service = :test

Factory

factory :user do
  membership_approval { Rack::Test::UploadedFile.new("#{Register::Engine.root}/spec/fixtures/membership.pdf", 'application/pdf') }
end

Mail example

def mail_example(user:)
  filename = user.membership_approval.filename.to_s
  attachments[filename] = user.membership_approval.download

  mail(
    ...
  )
end

When I run rspec I get the following error message when it tries to download the file.

Error message

ActiveStorage::FileNotFoundError:
# ------------------
# --- Caused by: ---
# Errno::ENOENT:
#   No such file or directory @ rb_sysopen - /Users/myuser/Projects/my_project/tmp/storage/nd/5h/nd5hlet2n2xa673f8v11ljbnru72

It works fine otherwise but I just can't seem to get it to work with rspec. When I'm debugging in rspec it looks like the file is attached to the object but not stored physically anywhere. Any ideas?

Best regards.

EDIT

I have also tried this approach in the factory but no luck, I still get the same error.

after(:build) do |user|
  user.membership_approval.attach(
    io: File.open("#{Register::Engine.root}/spec/fixtures/membership.pdf"),
    filename: 'membership.pdf',
    content_type: 'application/pdf'
  )
end

Solution

  • I encountered this same problem and I eventually figured out that the attachment is not persisted to the disk/storage solution until .save is called on the record.

    So, in your case, you could trigger this in your factory with:

    after(:build) do |user|
      user.membership_approval.attach(
        io: File.open("#{Register::Engine.root}/spec/fixtures/membership.pdf"),
        filename: 'membership.pdf',
        content_type: 'application/pdf'
      )
      user.save
    end