I'm using Active Storage in a personal project. I want to check if the max size of files is being validated. I don't wanna use a real file, but I don't know how to stub an object.
Here's the test code:
test "should not upload file bigger than max size allowed" do
refute @page.file.attached?
patch "/#{@page.url}", params: {
page: {
url: "/#{@page.url}",
file: my_stub_file_with_big_size
}
}
assert_response :not_acceptable
@page.reload
refute @page.file.attached?
end
Here's the validation on model:
def file_size
if file.attached? && file.byte_size > MAX_FILE_SIZE
file.purge
errors.add(:file, "File is too big. Max size is 20mb.")
end
end
Active Storage uses two tables in your application's database named active_storage_blobs and active_storage_attachments . After creating a new application (or upgrading your application to Rails 5.2), run rails active_storage:install to generate a migration that creates these tables.
1 What is Active Storage? Active Storage facilitates uploading files to a cloud storage service like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage and attaching those files to Active Record objects.
I read the code from your project, and I see that you've come up with an interesting solution, but here's another that matches your requirements.
Mocha is the de facto stubbing library for MiniTest fans, so add it to your Gemfile like so.
group :test do
gem 'mocha'
end
Then run bundle install
and require mocha in your test helper like so:
# test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
# add this line
require 'mocha/minitest'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
end
Place a small file named 'test.png' in test/fixtures/files/
. Note that my file is around 20KB in size, it's pretty small.
Add the following to test/models/page_test.rb
:
test 'file has max size' do
# get the path of the file
fixture_path = File.join(Rails.root, 'test', 'fixtures', 'files', 'test.png')
# open the file
fixture_file = File.open(fixture_path)
# stub the file size to 21 MB
fixture_file.stubs(:size).returns(21.megabytes)
# attach the file to your @page instance
@page.file.attach(io: fixture_file, filename: 'test.png')
# the record should now be invalid
refute @page.valid?
# it should not have an attachment
refute @page.file.attached?
# assert the error message matches a regex
assert_match /is too big/, @page.errors[:file].to_s
end
Let's make sure that a file of 20MB can be accepted by adding the following to test/models/page_test.rb
:
test 'file with valid size' do
# get the path of the file
fixture_path = File.join(Rails.root, 'test', 'fixtures', 'files', 'test.png')
# open the file
fixture_file = File.open(fixture_path)
# stub the file size to 20 MB
fixture_file.stubs(:size).returns(20.megabytes)
# attach the file to your @page instance
@page.file.attach(io: fixture_file, filename: 'test.png')
# the record should now be valid
assert @page.valid?
# it should have an attachment
assert @page.file.attached?
# probably unnecessary, but let's test that there are no errors on @page
assert_empty @page.errors[:file]
end
Let's add a controller test for the happy path:
test 'should update page' do
# fixture_file_upload knows where the fixtures folder is
# and makes sure we have a correctly signed file
fixture_file = fixture_file_upload('files/test.png', 'image/png')
# we need to stub the byte_size of any instance of ActiveStorage::Blob
# as that is what our validations are going to be run against
ActiveStorage::Blob.any_instance.stubs(:byte_size).returns(20.megabytes)
# make sure our ActiveStorage records are created
assert_difference ['ActiveStorage::Blob.count', 'ActiveStorage::Attachment.count'] do
# add our fixture file into the params
patch page_url, params: { page: { file: fixture_file } }
end
# make sure we are redirected to the right place
assert_redirected_to page_url
end
Time to test upload failure:
test 'should render edit template when update fails' do
# like before, we get correctly formatted test file by calling
# fixture_file_upload method and passing in the test file
fixture_file = fixture_file_upload('files/test.png', 'image/png')
# stub the byte_size to be 21MB
ActiveStorage::Blob.any_instance.stubs(:byte_size).returns(21.megabytes)
# make sure zero ActiveStorage records are created
assert_no_difference ['ActiveStorage::Blob.count', 'ActiveStorage::Attachment.count'] do
# send the request
patch page_url, params: { page: { file: fixture_file } }
end
# check the response body for an error message
assert_match /is too big/, response.body.to_s
end
That's it. Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With