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

EventWorker失败场景Spec执行失败,请求排查Stubbing问题

修复EventWorker失败场景Spec的Stub问题

核心问题分析

你的测试中described_class.jobs.count为0,说明要么Worker根本没被加入队列,要么Stub没命中导致Worker逻辑没走到抛出异常的分支,进而没有触发预期的任务状态。下面是针对性的修复步骤:


1. 严格匹配Stub的请求参数

Stub不生效是最常见的原因,必须保证Stub的POST请求和Worker中实际发起的请求完全一致,包括URL、请求头、请求体的每一个细节:

  • 比如Worker中发起请求的代码是:
    HTTParty.post(
      'https://your-api-domain.com/login',
      headers: { 'Content-Type' => 'application/json' },
      body: { user_id: user_id, token: auth_token }.to_json
    )
    
    那你的Stub必须精准对应:
    stub_request(:post, 'https://your-api-domain.com/login')
      .with(
        headers: { 'Content-Type' => 'application/json' },
        body: { user_id: 123, token: 'test-token' }.to_json
      )
      .to_return(
        status: 400,
        body: { status: 400, error: 'auth_failed', message: 'Invalid credentials' }.to_json,
        headers: { 'Content-Type' => 'application/json' }
      )
    
  • 用WebMock的断言验证Stub是否被命中:
    assert_requested(:post, 'https://your-api-domain.com/login', times: 1)
    
    如果断言失败,就说明匹配规则和实际请求不一致,需要调整。

2. 确保Worker以异步方式调用

如果测试中直接用EventWorker.new.perform(...)同步执行,不会触发Sidekiq的任务入队,jobs.count自然为0。必须用异步调用方法:

  • 错误写法:
    # 同步执行,不加入队列
    EventWorker.new.perform(user_id)
    
  • 正确写法:
    # 异步入队,会被Sidekiq统计
    EventWorker.perform_async(user_id)
    

3. 检查Worker的异常是否未被捕获

如果Worker的perform方法内部用begin/rescue吞掉了异常,即使走到else分支,也不会触发失败任务的统计:

  • 错误逻辑(异常被捕获):
    class EventWorker
      include Sidekiq::Worker
    
      def perform(user_id)
        begin
          http_response = HTTParty.post(...)
          if http_response.success?
            "Login Event Success"
          else
            raise "Login Event Failed"
          end
        rescue
          # 吞掉异常,任务被标记为成功
        end
      end
    end
    
  • 正确逻辑(异常直接抛出):
    class EventWorker
      include Sidekiq::Worker
    
      def perform(user_id)
        http_response = HTTParty.post(...)
        if http_response.success?
          "Login Event Success"
        else
          raise "Login Event Failed"
        end
      end
    end
    

4. 用正确的测试模式断言

使用Sidekiq的测试模式时,确保在正确的上下文中断言:

RSpec.describe EventWorker, type: :worker do
  let(:user_id) { 123 }

  it 'enqueues a failed job when login request fails' do
    # 配置Stub(按步骤1的规则写)
    stub_request(:post, 'https://your-api-domain.com/login')
      .with(...)
      .to_return(status: 400, body: ...)

    # 异步调用Worker
    EventWorker.perform_async(user_id)

    # 断言任务入队数
    expect(described_class.jobs.count).to eq(1)

    # 额外验证异常行为(可选,用inline模式)
    Sidekiq::Testing.inline! do
      expect { EventWorker.perform_async(user_id) }.to raise_error("Login Event Failed")
    end
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:52:53