You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ActiveStorage测试:Fixture中的Blob文件应存放于何处?

解决Active Storage Blob测试时的URI::InvalidURIError问题

这个问题我之前也碰到过,根源在于测试环境里Active Storage的Blob没有和实际存储服务正确绑定,导致service_url返回nil,最终触发了URI::InvalidURIError。下面是几个可行的解决办法:

方法一:直接在测试中动态创建Blob和Attachment(推荐)

Fixture的静态配置很容易因为路径、文件存在性问题出故障,直接在测试用例里创建关联对象会更可靠,还能自动处理文件上传到测试存储服务:

require 'test_helper'
class StorageControllerTest < ActionDispatch::IntegrationTest
  test "resources redirects to resource" do
    # 先准备好测试用的文件路径
    test_file_path = Rails.root.join('tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zma23ja')
    
    # 创建Blob并上传文件到测试存储服务
    blob = ActiveStorage::Blob.create_and_upload!(
      io: File.open(test_file_path),
      filename: 'summary.pdf',
      content_type: 'application/pdf'
    )
    
    # 创建Resource并关联Blob
    resource = Resource.create!(name: '2019_event_summary.pdf')
    resource.attach(blob)

    # 发起请求并验证重定向
    get resource_storage_path(resource.name)
    assert_redirected_to resource.file.service_url
  end
end

方法二:修复Fixture和测试环境配置

如果你坚持要用Fixture,需要确保以下几点:

  1. 配置测试环境的存储服务
    在config/environments/test.rb里指定测试用的存储服务:
config.active_storage.service = :test

然后在config/storage.yml中完善test配置,指向专门的测试存储目录:

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage/test") %>
  1. 确保测试文件存在于指定路径
    在测试启动前,把Fixture里的Blob对应的文件复制到测试存储目录。可以在test_helper.rb里添加钩子:
class ActiveSupport::TestCase
  setup do
    # 创建测试存储的目录结构
    test_blob_path = Rails.root.join("tmp/storage/test/aa/bb")
    FileUtils.mkdir_p(test_blob_path)
    
    # 复制测试文件到测试存储路径
    source_file = Rails.root.join('tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zma23ja')
    dest_file = test_blob_path.join('aabbWNGW1VrxZ8Eu4zma23ja')
    File.copy(source_file, dest_file) if File.exist?(source_file)
  end

  teardown do
    # 测试结束后清理测试存储文件
    FileUtils.rm_rf(Rails.root.join("tmp/storage/test"))
  end
end
  1. 更新Fixture的校验信息
    确保blobs.yml里的byte_size和checksum与实际文件匹配,避免因为校验失败导致服务无法生成有效URL。

为什么会出现这个错误?

Active Storage的service_url方法需要Blob对应的文件实际存在于配置的存储服务中,否则会返回nil。你的Fixture只定义了Blob的元数据,但没有把文件放到测试环境的存储路径下,所以调用service_url时返回nil,进而触发了URI::InvalidURIError(因为nil不是有效的URI)。

内容的提问来源于stack exchange,提问作者Tyler Rowsell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:09:16