ruby-on-rails 如何修复Twilio::REST::RestError在使用Rspec测试时出现的错误?

k5ifujac  于 2023-03-20  发布在  Ruby
关注(0)|答案(1)|浏览(185)

我刚开始使用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

其中Customer中的generate_verification_codesend_verification_code

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

Customerregistrations_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发送短信验证码号码)!
但有什么解决办法吗?

eivnm1vs

eivnm1vs1#

发生这种情况的原因是你的测试试图攻击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
    …

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

相关问题