RSpec中配置Fog Mock测试CarrierWave Google存储上传方法
CarrierWave 对接Fog Mock测试全流程(GCS存储场景)
一、前置依赖安装
- 先在项目Gemfile中声明所需依赖,执行
bundle install完成安装
# Gemfile gem 'carrierwave' gem 'fog-google' gem 'minitest' # Ruby生态通用轻量测试框架,新手友好
*注意:你提供的原始代码存在两处语法/逻辑错误,先修正为可运行版本:
store_dir方法直接写when分支,缺少case判断头部store_dir中调用file.getpath不存在,关联模型属性通过model.xxx调用
修正后的上传器与模型代码如下:
# test_uploader.rb class TestUploader < CarrierWave::Uploader::Base storage :fog def fog_credentials { provider: 'google', google_project: 'my project', google_json_key_location: 'myCredentialFile.json' } end def fog_provider 'fog/google' end def fog_directory 'test-bucket-name' end def store_dir case file.content_type when %r{application/.*}, /file/ "#{model.id}/file" when %r{audio/.*} "#{model.id}/audio" else raise "Invalid file type" end end end
# test_model.rb class TestModel # 非Rails环境需要手动引入上传器挂载方法 extend CarrierWave::Mount # 声明实例属性,对应模型主键和上传字段 attr_accessor :id, :images mount_uploader :images, TestUploader def initialize(id = 1) @id = id end end
二、测试环境Mock配置
Fog原生内置mock模式,所有存储操作在内存中完成,不会发起真实云服务请求,也不会产生费用。
在项目根目录新建test文件夹,创建测试初始化文件test_helper.rb:
# test/test_helper.rb require 'minitest/autorun' require 'carrierwave' require 'fog/google' require_relative '../test_uploader' require_relative '../test_model' # 核心开关:开启Fog全局mock模式 Fog.mock! # 预创建mock环境下的存储桶,避免上传时报桶不存在错误 Fog::Storage.new( provider: 'google', google_project: 'test-project', # mock模式下不需要真实密钥,填合法格式的字符串即可 google_json_key_string: '{"type":"service_account"}' ).put_bucket('test-bucket-name') # 配置CarrierWave测试临时目录,避免污染本地文件 CarrierWave.configure do |config| config.root = File.expand_path('../tmp_test', __dir__) config.cache_dir = 'cache' end
三、单元测试用例编写
在test目录下创建测试文件test_uploader_test.rb,覆盖核心上传逻辑:
# test/test_uploader_test.rb require_relative './test_helper' class TestUploaderTest < Minitest::Test def setup # 每个测试用例执行前初始化干净的测试数据 @model = TestModel.new(1001) # 生成临时测试音频文件 File.write(File.join(CarrierWave.root, 'test.mp3'), 'fake audio content') @audio_file = File.open(File.join(CarrierWave.root, 'test.mp3')) # 生成临时测试普通文件 File.write(File.join(CarrierWave.root, 'test.bin'), 'fake file content') @regular_file = File.open(File.join(CarrierWave.root, 'test.bin')) end def teardown # 每个用例执行后清空mock数据和临时文件 Fog::Mock.reset FileUtils.rm_rf(CarrierWave.root) end def test_audio_file_upload_path @model.images = @audio_file # 非Rails环境需要手动触发存储,Rails/ActiveRecord模型保存时会自动触发 @model.images.store! # 校验存储路径符合规则 assert_match %r{1001/audio/}, @model.images.path # 校验文件在mock存储中存在 assert @model.images.exists? # 校验文件内容正确 assert_equal 'fake audio content', @model.images.file.read end def test_regular_file_upload_path @model.images = @regular_file @model.images.store! assert_match %r{1001/file/}, @model.images.path assert @model.images.exists? end def test_invalid_file_raise_error File.write(File.join(CarrierWave.root, 'test.txt'), 'invalid content') invalid_file = File.open(File.join(CarrierWave.root, 'test.txt')) @model.images = invalid_file assert_raises(RuntimeError, "Invalid file type") do @model.images.store! end end end
四、测试执行与验证
在项目根目录执行测试命令:
ruby test/test_uploader_test.rb
预期结果:
- 执行过程无外网请求,无GCS权限报错
- 3个测试用例全部通过
- 本地临时目录
tmp_test在测试结束后自动清空
如果你是在Rails项目中使用,不需要手动引入
CarrierWave::Mount,也不需要手动调用store!,ActiveRecord的保存回调会自动触发上传逻辑,Fog mock配置直接写到config/environments/test.rb中即可。
内容的提问来源于stack exchange,提问作者sagar verma
相关产品推荐
相关产品推荐

