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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:35:17