如何在使用 Rspec 进行测试时修复 Twilio::REST::RestError



我是RSpec测试新手,不知道如何在测试创建新Customer时修复此错误,我的CustomerController

class Api::V1::Customers::RegistrationsController < DeviseTokenAuth::RegistrationsController
  def create
        customer = Customer.new(email: params[:email],
                            password: params[:password],
                            password_confirmation: params[:password_confirmation],
                            first_name: params[:first_name],
                            last_name: params[:last_name],
                            telephone_number: params[:telephone_number],
                            mobile_phone_number: params[:mobile_phone_number])
        if customer.save
          customer.generate_verification_code
          customer.send_verification_code
          render json: {message: 'A verification code has been sent to your mobile. Please fill it in below.'}, status: :created
        else
          render json: customer.errors
        end
     end
  end
end

generate_verification_codesend_verification_codeCustomer

class Customer < ActiveRecord::Base
  def generate_verification_code
    self.verification_code = rand(0000..9999).to_s.rjust(4, "0")
    save
  end
  def send_verification_code
    client = Twilio::REST::Client.new
    client.messages.create(
      from: Rails.application.secrets.twilio_phone_number,
      to: customer.mobile_phone_number,
      body: "Your verification code is #{verification_code}"
    )
  end
end

和测试文件,用于Customer registrations_controller_spec.rb

require 'rails_helper'
RSpec.describe Api::V1::Customers::RegistrationsController, type: :controller do
    let(:customer) { FactoryBot.create(:customer) }
    before :each do
        request.env['devise.mapping'] = Devise.mappings[:api_v1_customer]
    end
    describe "Post#create" do
        it 'creates a new customer' do
            post :create, params: attributes_for(:customer)
            expect(response).to have_http_status(:created)
        end
    end
end

运行测试后,我收到此错误:

 Failure/Error:
   client.messages.create(
     from: Rails.application.secrets.twilio_phone_number,
     to: customer.mobile_phone_number
     body: "Your verification code is #{verification_code}"
   )
 Twilio::REST::RestError:
   Unable to create record: The requested resource /2010-04-01/Accounts//Messages.json was not found

我知道这个错误正在发生,因为在测试中它不应该调用外部 API(当 Twilio 向号码发送短信验证码时(!

但是有什么想法可以解决这个问题吗?

发生这种情况的原因是您的测试正在尝试访问 twilio 的 API,并且可能没有针对测试环境的正确配置。要测试像Twilio这样的第三方调用,你需要模拟HTTP请求。有人在评论中建议VCR。但是,在我看来,您应该通过创建一个虚假的 twilio 适配器来模拟 TwilioClient 本身。像这样的东西——

class TwilioAdapter
  attr_reader :client
  def initialize(client = Twilio::REST::Client.new)
    @client = client
  end
  def send_sms(body:, to:, from: Rails.application.secrets.twilio_phone_number)
    client.messages.create(
      from: from,
      to:   to,
      body: body,
    )
  end
end

将客户中的send_verification_code方法更改为 –

def send_verification_code
  client = TwilioAdapter.new
  client.send_sms(
    to: customer.mobile_phone_number,
    body: "Your verification code is #{verification_code}"
  )
end

现在你在控制器测试块之前,模拟TwilioAdapter的send_sms方法。

require 'rails_helper'
RSpec.describe Api::V1::Customers::RegistrationsController, type: :controller do
    let(:customer) { FactoryBot.create(:customer) }
    before :each do
      request.env['devise.mapping'] = Devise.mappings[:api_v1_customer]
      # Here's the expectation
      expect_any_instance_of(TwilioAdapter).to receive(:send_sms).with(hash_including(:body, :to))
    end
    …

这应该可以解决问题。

无论如何,我强烈反对这种通过模型同步进行第 3 部分调用的模式。我建议创建一个带有通用接口的 SMS 服务,该服务使用上面提到的 twilio 适配器发送 SMS,并使用 sidekiq 异步执行此操作。https://www.twilio.com/blog/2015/10/delay-api-calls-to-twilio-with-rails-active-job-and-sidekiq.html

最新更新