In rails tests. I have a basic model with only activestorage:
class User < ApplicationRecord
has_one_attached :avatar
end
I\'m trying
Lets say you have a test for the model user, the default UserTest#test_the_truth
rails test test/models/user_test.rb
I suppose you are getting an error
Errno::ENOENT: No such file or directory @ rb_sysopen
during the test, because of an error in your path,
you must add 'fixtures'
, it should be like:
# users.yml
one:
name: 'Jim Kirk'
avatar: <%= File.open Rails.root.join('test', 'fixtures', 'files', 'image.png').to_s %>
but now you should have this error: ActiveRecord::Fixture::FixtureError: table "users" has no column named "avatar".
That's correct, because ActiveStorage uses two tables to work: active_storage_attachments
and active_storage_blobs
.
So, you need to remove avatar column from users.yml
and add two new files:
(Disclaimer See also comments below: "no need create own models, so instead of ActiveStorageAttachment
you could use original ActiveStorage::Attachment
and place fixture under active_storage folder" and refer also to https://stackoverflow.com/a/55835955/5239030)
# active_storage_attachments.yml
one:
name: 'avatar'
record_type: 'User'
record_id: 1
blob_id: 1
and
# active_storage_blobs.yml
one:
id: 1
key: '12345678'
filename: 'file.png'
content_type: 'image/png'
metadata: nil
byte_size: 2000
checksum: "123456789012345678901234"
Also, in App/models
, add, even if not required for the ActiveStorage to work.
# active_storage_attachment.rb
class ActiveStorageAttachment < ApplicationRecord
end
and
# active_storage_blob.rb
class ActiveStorageBlob < ApplicationRecord
end
Then the UserTest#test_the_truth
succeed.
But better get rid of active_storage_attachment.rb
and active_storage_blob.rb
and follow another way to test.
For testing if the attachment is working, better test the controller, for example adding this code in test/controllers/users_controller_test.rb
:
require 'test_helper'
class UserControllerTest < ActionController::TestCase
def setup
@controller = UsersController.new
end
test "create user with avatar" do
user_name = 'fake_name'
avatar_image = fixture_file_upload(Rails.root.join('test', 'fixtures', 'files', 'avatar.png'),'image/png')
post :create, params: {user: {name: user_name, avatar: avatar_image}}
end
end
Check the folder tmp/storage
, should be empty.
Launch the test with: rails test test/controllers/users_controller_test.rb
It should succeed, then if you check again in tmp/storage
, you should find some folders and files generated by the test.
Edit after comments:
If you need to test the callbacks on User
model, then this should work:
# rails test test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
test "should have avatar attached" do
u = User.new
u.name = 'Jim Kirk'
file = Rails.root.join('test', 'fixtures', 'files', 'image.png')
u.avatar.attach(io: File.open(file), filename: 'image.png') # attach the avatar, remove this if it is done with the callback
assert u.valid?
assert u.avatar.attached? # checks if the avatar is attached
end
end
I don't know your callback, but I hope this gives you some hint.