Rails系统测试中Turbo Action Cable关联Job未执行的原因及解决
问题
基于Rails、Turbo和Action Cable开发的项目,开发环境运行正常,但系统测试环节Action Cable无响应。排查发现系统测试中Action Job既未入队也未执行,在create动作调试时甚至无法找到变量。测试断言expect(PlayJob).to have_been_enqueued失败,报错信息:
Failure/Error: expect(PlayJob).to have_been_enqueued expected to enqueue exactly 1 jobs, but enqueued 0
相关代码
系统测试代码(spec/system/grids_spec.rb)
RSpec.describe 'Grids', type: :system do it 'creates grid' do visit root_path click_on 'Create Grid' expect do sleep 0.2 end.to change { find('#grid').html } end end
控制器代码(app/controllers/grids_controller.rb)
class GridsController < ApplicationController def create @grid_data = GridData.new(**grid_params) if @grid_data.valid? play else render :new, status: :unprocessable_entity end end private def play render :play, status: :created PlayJob.perform_later(**@grid_data.attributes) end end
Job代码(app/jobs/play_job.rb)
class PlayJob < ApplicationJob queue_as :default def perform(**grid_attributes) GridData.new(grid_attributes).to_grid.play end end
Grid类代码(lib/grid.rb)
class Grid def play print 2.upto(@phases) do sleep(@phase_duration) next_phase print end end def print Turbo::StreamsChannel.broadcast_update_to( 'play', target: 'grid', partial: 'grids/grid', locals: { grid: self } ) end end
解决方案
1. 配置系统测试的Job环境
Rails系统测试默认未启用Job队列断言支持,且不会自动执行Job。需在spec/spec_helper.rb或spec/system_helper.rb中添加配置:
RSpec.configure do |config| config.before(:each, type: :system) do # 启用Job队列测试匹配器 require 'rspec/rails/matchers/active_job' # 配置Job入队模式::test用于断言,:inline则立即执行Job ActiveJob::Base.queue_adapter = :test end end
若需要Job在测试中立即执行以触发Action Cable更新,可将适配器改为:inline。
2. 确保表单参数正确提交
测试中点击"Create Grid"时,若未填充必要表单字段,会导致@grid_data验证失败,跳过play方法执行。需补充表单填充步骤:
it 'creates grid' do visit root_path # 根据实际表单字段填充参数,示例为rows/columns fill_in 'Rows', with: 5 fill_in 'Columns', with: 5 click_on 'Create Grid' expect(PlayJob).to have_been_enqueued expect do sleep 0.5 end.to change { find('#grid').html } end
3. 验证@grid_data的有效性
若@grid_data.valid?返回false,play方法不会被调用。可在控制器中添加日志排查验证问题:
def create @grid_data = GridData.new(**grid_params) Rails.logger.debug "GridData验证错误:#{@grid_data.errors.full_messages}" if @grid_data.valid? play else render :new, status: :unprocessable_entity end end
4. 启用系统测试的Action Cable支持
需确保测试环境配置了Cable连接,在spec/system_helper.rb中添加:
RSpec.configure do |config| config.before(:each, type: :system) do driven_by :selenium, using: :chrome, screen_size: [1400, 1400] # 用Puma启动服务器以支持Action Cable Capybara.server = :puma, { Silent: true } end end
同时检查config/cable.yml的测试环境配置:
test: adapter: async
内容的提问来源于stack exchange,提问作者Chiara Ani
相关产品推荐
相关产品推荐

