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

如何用WebMock测试Signalwire API消息获取Ruby方法?

问题描述

我正在为以下从Signalwire API获取消息的Ruby方法编写测试:

#fetch message from api

def message_instance
    project_id = ENV['SIGNALWIRE_PROJECT_KEY']
    project_tkn = ENV['SIGNALWIRE_TOKEN']
    host_url = ENV['SIGNALWIRE_HOST']
    @client = Signalwire::REST::Client.new project_id, project_tkn, signalwire_space_url: host_url
    message = @client.messages(sid).fetch
end

我用FactoryBot模拟了一个状态为received的消息:

@message = build :message, status: :received

但我不知道怎么全面测试这个方法的每一行,希望有人指导我如何用WebMock正确存根请求。

补充:已尝试的测试代码及错误

我写了如下测试代码:

describe 'message_instance' do
    it 'returns message instance' do
      
      allow(ENV).to receive(:[]).with('SIGNALWIRE_PROJECT_KEY').and_return('AC123')
      @message = build :message, status: 'received', sid: '123456789'
     
     
      @message.message_instance.should eq @client
      
    end
end

但出现了以下错误:

"BUNDLER_ORIG_RUBYLIB"=>"BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL", "BUNDLER_ORIG_RUBYOPT"=>"BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL", "BUNDLE_GEMFILE"=>"/vagrant/oyetext-backend/Gemfile", "BUNDLE_BIN_PATH"=>"/usr/share/rvm/rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/bundler-2.1.4/libexec/bundle", "BUNDLER_VERSION"=>"2.1.4", "RUBYOPT"=>"-r/usr/share/rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/bundler/setup", "RUBYLIB"=>"", "RAILS_ENV"=>"test", "SIGNALWIRE_PROJECT_KEY"=>"test", "SIGNALWIRE_TOKEN"=>"test", "SIGNALWIRE_NUMBER"=>"+19999999999"} received :[] with unexpected arguments
         expected: ("SIGNALWIRE_PROJECT_KEY")
              got: ("SIGNALWIRE_TOKEN")
        Please stub a default value first if message might be received with other args as well. 

解决步骤

1. 修复ENV存根问题

你只存根了SIGNALWIRE_PROJECT_KEY,但方法里还用到了SIGNALWIRE_TOKEN和SIGNALWIRE_HOST,必须把这三个环境变量都存根,或者给ENV设置默认存根避免报错:

方法一:逐个存根所有用到的环境变量

describe 'message_instance' do
  it 'returns message instance' do
    # 存根方法中用到的所有环境变量
    allow(ENV).to receive(:[]).with('SIGNALWIRE_PROJECT_KEY').and_return('AC123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_TOKEN').and_return('TOKEN123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_HOST').and_return('your-space.signalwire.com')

    @message = build :message, status: 'received', sid: '123456789'
    # 后续测试逻辑
  end
end

方法二:设置ENV默认存根(更简洁)

describe 'message_instance' do
  before do
    # 保留其他环境变量的原始行为,只覆盖需要的字段
    allow(ENV).to receive(:[]).and_call_original
    allow(ENV).to receive(:[]).with('SIGNALWIRE_PROJECT_KEY').and_return('AC123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_TOKEN').and_return('TOKEN123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_HOST').and_return('your-space.signalwire.com')
  end

  it 'returns message instance' do
    @message = build :message, status: 'received', sid: '123456789'
    # 后续测试逻辑
  end
end

2. 用WebMock存根Signalwire API请求

要测试@client.messages(sid).fetch这一行,需要存根Signalwire的消息获取API。Signalwire的消息详情API端点格式通常为https://<your-space>.signalwire.com/api/laml/2010-04-01/Accounts/<ProjectID>/Messages/<MessageSID>.json

示例代码:

require 'webmock/rspec'

describe 'message_instance' do
  before do
    # 存根环境变量
    allow(ENV).to receive(:[]).and_call_original
    allow(ENV).to receive(:[]).with('SIGNALWIRE_PROJECT_KEY').and_return('AC123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_TOKEN').and_return('TOKEN123')
    allow(ENV).to receive(:[]).with('SIGNALWIRE_HOST').and_return('test-space.signalwire.com')

    # 存根Signalwire API请求
    message_sid = '123456789'
    stub_request(:get, "https://test-space.signalwire.com/api/laml/2010-04-01/Accounts/AC123/Messages/#{message_sid}.json")
      .with(
        headers: {
          'Authorization' => "Basic #{Base64.strict_encode64('AC123:TOKEN123')}"
        }
      )
      .to_return(
        status: 200,
        body: {
          sid: message_sid,
          status: 'received',
          # 按需添加其他消息字段
        }.to_json,
        headers: { 'Content-Type' => 'application/json' }
      )
  end

  it 'returns the fetched message instance' do
    @message = build :message, status: 'received', sid: '123456789'
    fetched_message = @message.message_instance

    # 验证返回的消息属性
    expect(fetched_message.sid).to eq('123456789')
    expect(fetched_message.status).to eq('received')
    # 可选:验证客户端初始化是否正确
    expect(@message.instance_variable_get(:@client).project_id).to eq('AC123')
  end
end

3. 覆盖核心测试点

  • 验证环境变量是否被正确读取并传入客户端初始化
  • 验证客户端是否正确调用了消息获取API
  • 验证返回的消息实例属性符合预期(状态、SID等)
  • 可选:测试API请求失败场景(如返回404,验证方法是否抛出对应异常)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:35:26