I have just switched to using ActiveStorage on rails 5.1.4 and I am new to TDD and struggling to figure out how to test a model that has_one_attached :avatar
I solved using
FactoryBot.define do
factory :culture do
name 'Soy'
after(:build) do |culture|
culture.image.attach(io: File.open(Rails.root.join('spec', 'factories', 'images', 'soy.jpeg')), filename: 'soy.jpeg', content_type: 'image/jpeg')
end
end
end
After
describe '#image' do
subject { create(:culture).image }
it { is_expected.to be_an_instance_of(ActiveStorage::Attached::One) }
end
Problem solved. After tracing the error to the ActiveStorage::Blob::upload method, where it said: Uploads the io to the service on the key for this blob.
I realized I had not set the active_storage.service for the Test environment. Simply put, just add:
config.active_storage.service = :test
To config/environments/test.rb file
Here is how I solved it
# model
class Report < ApplicationRecord
has_one_attached :file
end
# factory
FactoryBot.define do
factory :report, class: Report do
any_extra_field { 'its value' }
end
end
# spec
require 'rails_helper'
RSpec.describe Report, type: :model do
context "with a valid file" do
before(:each) do
@report = create(:report)
end
it "is attached" do
@report.file.attach(
io: File.open(Rails.root.join('spec', 'fixtures', 'file_name.xlsx')),
filename: 'filename.xlsx',
content_type: 'application/xlsx'
)
expect(@report.file).to be_attached
end
end
end
I hope it help you
In config/environments/test.rb
config.active_storage.service = :test
In your spec
it {expect(valid_user.avatar).to be_attached}
I was running into a similar nil error (Module::DelegationError: to_model delegated to attachment, but attachment is nil), but it was only occurring when multiple tests were using the same factory.
The problem appears to be that the cleanup from the previous test's teardown was deleting the file after it was attached on the next factory call. The key was updating the ActiveJob queue adapter to inline so that the file would be deleted right away.
Add both of these settings to config/environments/test.rb:
# Use inline job processing to make things happen immediately
onfig.active_job.queue_adapter = :inline
# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test