Activestorage fixtures attachments

前端 未结 3 1957
忘掉有多难
忘掉有多难 2021-01-01 15:01

In rails tests. I have a basic model with only activestorage:

class User < ApplicationRecord
  has_one_attached :avatar
end

I\'m trying

3条回答
  •  生来不讨喜
    2021-01-01 15:31

    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.

提交回复
热议问题