I need to deal a lot with one external API. Each instance should give access to namespace resources, e.g. client.accounts.payout_history
, client.accounts.list
. To do so I've created a client using Faraday gem which now I want test by RSpec with build-in Faraday::Adapter (docs for the reference). Here is my code:
Fake client to have control of what's going on
# clients/isor/fake_client.rb
module Isor
class FakeClient
BASE_URL = 'https://test-api.net/api/v1/'
def initialize(stubs:, api_key: 'fake')
@api_key = api_key
@stubs = stubs
end
def accounts
Resources::Accounts.new
end
def connection
@connection ||= Faraday.new do |conn|
conn.url_prefix = BASE_URL
conn.request :json
conn.response :json, content_type: 'application/json'
conn.adapter :test, @stubs
end
end
attr_reader :api_key
end
end
Place where all http methods are handled:
# clients/isor/resource.rb
module Isor
class Resource
def initialize
@client = client
end
def get(url, params: {}, headers: {})
handle_response client.connection.get(url, params, default_headers.merge(headers))
end
# (...) other http methods
private
def client
return @client ||= Client.new unless Rails.env.test?
@client ||= FakeClient.new(stubs: @stubs)
end
def default_headers
{ Authorization: "Bearer #{client.api_key}" }
end
def handle_response(response)
return response.body if response.success?
# (...) some code if error
end
end
end
Class which I want to test:
# clients/isor/resources/accounts.rb
module Isor
module Resources
class Accounts < Isor::Resource
def initialize(stubs: nil)
@stubs = stubs
end
def payout_history(platform_merchant_id:)
get("merchants/#{platform_merchant_id}/payouts")
end
# (...) other endpoints
end
end
end
My RSpec test:
require 'rails_helper'
RSpec.describe Isor::Resources::Accounts do
let(:stub) do
Faraday::Adapter::Test::Stubs.new do |stub|
stub.get("api/v1/merchants/#{platform_merchant_id}/payouts") do
[200, { 'Content-type' => 'application/json' }, 'test response']
end
end
end
let(:platform_merchant_id) { '1234' }
subject { described_class.new(stubs: stub) }
describe '#payout_history' do
it 'return payout history' do
expect(subject.payout_history(platform_merchant_id:)).to eq('test response')
end
end
end
For reasons unknown to me I get an error:
Faraday::Adapter::Test::Stubs::NotFound: no stubbed request for get https://test-api.net/api/v1/merchants/1234/payouts