How can I access an ActiveStorage object via URL in a test environment?

两盒软妹~` 提交于 2019-12-22 11:37:24

问题


Given a model that has an ActiveStorage attachment

class MyObject
  has_one_attached :avatar
end

In a dev environment I am able to retrive the avatar as a StringIO object.

obj = MyObject.new( { valid params } )
file = File.open( Rails.root.join( "spec/support/images/test_image.jpg" ))
obj.avatar.attach( io: file, filename: "test_image.jpg" )
obj.save

version = obj.avatar.variant( resize: '200x200>').processed
version_url = Rails.application.routes.url_helpers.url_for( version )
download = open(version_url)
download.class 
=> StringIO

When I attempt to do the same think in a test environment, open(version_url) returns

Errno::ECONNREFUSED Exception: Failed to open TCP connection to localhost:3000 (Connection refused - connect(2) for "localhost" port 3000)

Has anyone managed to successfully download activestorage attachments within a test? How should I configure the test environment to achieve this?

My test environment already has

config.active_storage.service = :test
Rails.application.routes.default_url_options = {host: "localhost:3000"}

What have I overlooked?

EDIT

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

回答1:


Stored files are accessed through the Rails application server

Active Storage attachments generate URLs that point to the application. The application URL endpoint then redirects to the real file. This decouples the physical location of the file from the URL and provides indirection which is useful for features such as mirroring.

This also means that in order to access a file using its generated URL, a Rails application server must be running...

Server does not run in test environment

The Rails test suite does not start up a server when running the tests. The tests typically don’t need one in order to run.

Errno::ECONNREFUSED Exception: Failed to open TCP connection to localhost:3000 (Connection refused - connect(2) for "localhost" port 3000)

This error occurs because the open call tries to request the file at the server location localhost:3000. Because there’s no server running, it fails.

Even if you start up a development server, it will still fail because the Active Storage Attachment and Blob records are stored in the test database, not the development database.

Bypass the app server and get a path directly to the file

In order to get access to a file or variant in your test suite, you need to bypass the application server and get a direct path to the file on disk.

The Active Storage test suite source code shows us how to do this:

blob_or_variant.service.send(:path_for, blob_or_variant.key)

View Source

This will return a file path (on disk) which you can then open using File.open.

Fixing the example above

In the example above, change

download = open(version_url) # BAD: tries to access using HTTP

to

download = File.open( version.service.send(:path_for, version.key) )

Use stubs to avoid network requests in the test suite

If you are testing code which accesses files using HTTP, it’s best practice to stub the network call to avoid it altogether.

There’s some good examples of how to do this in RSpec here:
RSpec how to stub open?



来源:https://stackoverflow.com/questions/52071890/how-can-i-access-an-activestorage-object-via-url-in-a-test-environment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!