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

Rails 7.1+RSpec测试因Active Storage附件冻结求助

问题:RSpec测试因ActiveStorage附件冻结并抛出反序列化错误

环境信息

  • Ruby 3.3.0
  • Rails 7.1.3.2
  • factory_bot 6.4.6
  • mini_magick 4.12.0
  • rspec-rails 6.1.2
  • OSX

问题现象

浏览器中所有功能运行正常,但执行涉及Song模型的RSpec测试时,进程大概率冻结(Intel处理器90%概率、ARM处理器60%概率),测试输出停滞在:

Song
  associations
    is expected to belong to album required: true
  validates
    is expected to validate that :artist_name cannot be empty/falsy
  #ordered
    when have only one disc

仅当FactoryBot中为Album的cover属性添加附件时触发问题,移除附件则测试正常。测试日志中出现错误:

Error performing ActiveStorage::AnalyzeJob (Job ID: ee23c48f-38ed-4a96-a3f5-a3b11645a028) from Async(default) in 5.02ms: ActiveJob::DeserializationError (Error while trying to deserialize arguments: undefined method `clear' for nil):

相关代码

Album模型

class Album < ApplicationRecord
  has_one_attached :cover do |attachable|
    attachable.variant :thumb, resize: '100x100'
    attachable.variant :medium, resize: '400x400'
  end

  # Associations
  has_many :songs, dependent: :destroy

  # Validations
  validates :title, :artist_name, presence: true
  validates :cover, attached: true
end

Song模型

class Song < ApplicationRecord
  # Attachments
  has_one_attached :audio

  # Associations
  belongs_to :album

  # Scopes
  scope :ordered, -> { order(disk_number: :asc, track_number: :asc) }
end

Song的RSpec测试

RSpec.describe Song do
 subject(:song) { create(:song, album:) }

 let(:album) { create(:album, cover: file_fixture('cover.jpg')) }

 describe 'associations' do
   it { expect(song).to belong_to('album') }
 end

 describe 'validates' do
   it do
     expect(album).to validate_presence_of(:title)
     expect(album).to validate_presence_of(:artist_name)
   end
 end

 describe '#ordered' do
   subject(:ordered) { described_class.ordered }

   context 'when have only one disc' do
     let(:song1) { create(:song, track_number: 1, album:) }
     let(:song2) { create(:song, track_number: 2, album:) }
    
     it 'returns array with correct ordered songs' do
       expect(ordered).to eq([song, song2])
     end
    end
    
    context 'when you have two disc and the same track number' do
      let(:song1) { create(:song, track_number: 1, disk_number: 1, album:) }
      let(:song2) { create(:song, track_number: 1, disk_number: 2, album:) }
    
      it 'returns array with ordered by track and disc' do
        expect(ordered).to eq([song1, song2])
      end
    end
 end

...

end

Album的FactoryBot定义

FactoryBot.define do
  factory :album do
    title { 'MyString' }
    artist_name { 'Artist' }
    label { 'MyString' }
    upc { 'MyString' }
    release_date { '2024-03-24 13:14:12' }
    cover { File.open('spec/fixtures/cover.jpg') }
  end
end

解决方案思路

  1. 强制ActiveStorage任务同步执行
    在config/environments/test.rb中配置,避免异步任务引发的序列化问题:

    config.active_job.queue_adapter = :inline
    # 或者仅针对ActiveStorage的任务
    config.active_storage.queues.analyze = :inline
    config.active_storage.queues.purge = :inline
    
  2. 优化FactoryBot的附件处理
    改用Rails提供的fixture_file_upload确保文件对象正确处理:

    factory :album do
      # ...其他属性
      cover { fixture_file_upload('cover.jpg', 'image/jpeg') }
    end
    
  3. 跳过附件分析任务
    在测试环境中禁用ActiveStorage的附件分析,减少测试中的额外操作:

    # config/environments/test.rb
    config.active_storage.analyze = false
    

    或者在测试中临时跳过:

    RSpec.describe Song do
      before do
        allow_any_instance_of(ActiveStorage::Blob).to receive(:analyze_later).and_return(nil)
      end
      # ...测试内容
    end
    
  4. 验证MiniMagick依赖
    确保OSX上已安装ImageMagick(执行brew install imagemagick),并在Rails控制台验证图片处理是否正常:

    image = MiniMagick::Image.open('spec/fixtures/cover.jpg')
    image.resize('100x100')
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:31:03