如何用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
相关产品推荐
相关产品推荐

