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

Rails 7.2升级后Sidekiq+ActiveJob测试清理失败问题咨询

Rails 7.2 + Sidekiq 测试数据库清理问题解决方案

先明确核心冲突原因

Rails 7.2 默认启用了 ActiveJob::Base.transactional_enqueue 特性——它会把任务入队操作包裹在当前数据库事务中,只有事务提交时,Job才会真正推送到Sidekiq队列。但你之前沿用的database_cleaner事务策略(每个测试开事务、结束后回滚)会触发两种矛盾:

  • 测试事务回滚前,Sidekiq Worker可能已经拾取任务,读取到未提交的脏数据,或者事务回滚后数据直接消失,导致Worker报错;
  • 如果测试事务直接回滚,Job根本不会被入队,测试逻辑完全失效。

针对性解决方案,分场景选择

场景1:仅验证Job业务逻辑,不需要真异步

直接让Job同步执行,彻底规避跨进程数据库问题:

  • 全局配置(config/environments/test.rb):
    config.active_job.immediately_enqueue_jobs = true
    
  • 临时切换(针对特定Cucumber步骤):
    # 触发Job前开启同步
    ActiveJob::Base.immediately_enqueue_jobs = true
    # 执行触发Job的操作(比如用户提交表单)
    # 执行完恢复异步
    ActiveJob::Base.immediately_enqueue_jobs = false
    

这种方式下,Job和测试代码共享同一个事务,database_cleaner的事务策略完全兼容,不需要修改清理逻辑。

场景2:必须模拟生产环境的真异步执行

这种情况确实要放弃事务策略,但不用全局修改,仅针对Sidekiq相关测试切换:

  1. 在Cucumber的features/support/env.rb中配置策略切换:
    # 默认用事务策略保证测试速度
    DatabaseCleaner.strategy = :transaction
    
    # 标记@sidekiq的测试场景切换为截断策略
    Before('@sidekiq') do
      DatabaseCleaner.strategy = :truncation
      DatabaseCleaner.start
    end
    
    After('@sidekiq') do
      DatabaseCleaner.clean
      # 切回默认事务策略
      DatabaseCleaner.strategy = :transaction
    end
    
  2. 给需要异步执行Job的Cucumber场景加标签:
    @sidekiq
    Scenario: 用户提交表单后后台处理数据
      Given 用户填写并提交表单
      When 后台任务完成处理
      Then 页面显示处理后的结果
    

额外优化建议

  • 截断策略比事务慢,所以只在必要场景使用,其余测试保持事务策略;
  • 在测试套件启动前执行一次全局截断清理,减少单测试的截断开销:
    DatabaseCleaner.clean_with :truncation
    
  • 确保config/database.yml的test环境pool值足够,避免Sidekiq Worker出现数据库连接耗尽的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:16:01