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,需要确保以下几点:
- 配置测试环境的存储服务
在config/environments/test.rb里指定测试用的存储服务:
config.active_storage.service = :test
然后在config/storage.yml中完善test配置,指向专门的测试存储目录:
test: service: Disk root: <%= Rails.root.join("tmp/storage/test") %>
- 确保测试文件存在于指定路径
在测试启动前,把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
- 更新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
相关产品推荐
相关产品推荐

