如何在 Active Storage 测试中存根文件大小?(测试::单位)

Mat*_*ard 6 testing ruby-on-rails file mocking rails-activestorage

我在个人项目中使用 Active Storage 。我想检查文件的最大大小是否正在验证。我不想使用真实的文件,但我不知道如何存根对象。

这是测试代码:

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
Run Code Online (Sandbox Code Playgroud)

这是模型的验证:

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
Run Code Online (Sandbox Code Playgroud)

ste*_*och 3

我阅读了您项目中的代码,发现您提出了一个有趣的解决方案,但这里有另一个符合您的要求的解决方案。

第 1 步 - 添加摩卡

Mocha是MiniTest 粉丝事实上的存根库,因此将其添加到您的 Gemfile 中,如下所示。

group :test do
  gem 'mocha'
end
Run Code Online (Sandbox Code Playgroud)

然后在测试助手中运行bundle install并要求 mocha,如下所示:

# 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
Run Code Online (Sandbox Code Playgroud)

第 2 步 - 创建虚拟测试文件

将一个名为“test.png”的小文件放入test/fixtures/files/. 请注意,我的文件大小约为 20KB,相当小。

第 3 步 - 添加单元测试

将以下内容添加到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
Run Code Online (Sandbox Code Playgroud)

第 4 步 - 在最大文件大小边界内进行测试

让我们通过添加以下内容来确保可以test/models/page_test.rb接受 20MB 的文件:

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
Run Code Online (Sandbox Code Playgroud)

第 5 步 - 为快乐路径添加控制器测试

让我们为快乐路径添加一个控制器测试:

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
Run Code Online (Sandbox Code Playgroud)

第 6 步 - 为悲伤路径添加控制器测试

测试上传失败的时间:

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
Run Code Online (Sandbox Code Playgroud)

就是这样。希望能帮助到你。