Little Thing — Wrapping External Services

Danny Smith
2 min readMar 4, 2020

This is part of my Little Things series.

Imagine we are using an external service in a ruby app, probably a gem of some sort…

require 'beerclient'beer_api_client = BeerAPIClient.new(API_KEY)beer_api_client.get_beers

What’s wrong with this?

  1. We shouldn’t mock it, since we don’t own it.
  2. If we do mock it, our unit tests won’t fail if they release a breaking change to the API.
  3. We’ll get screwed if they release a breaking change. Upgrading will be hard, because we will have to fix that error in multiple places.
  4. We have to catch exceptions that are not our own in our application code.

To fix this, we should wrap it in a simple wrapper class:

require 'beerclient'class BeerClient
API_KEY = ENV['BEER_API_KEY']
def initialize
@client = BeerAPIClient.new(API_KEY)
end
def get_beers
@client.get_beers
rescue BeerAPIClient::BeerError => e
raise OurSystem::BeerAPIError, e
end
end
  • We can now mock this, because we own it’s interface.
  • We can move the require and API key code in here and make our external interface cleaner.
  • We can write a simple integration test that just tests how this client interacts with the Beer API. It will be small.
  • If they release a breaking change, we can upgrade the gem easily and only need to update this class and the associated test.
  • We can catch specific exceptions from the gem and re-raise our own exceptions. This means we can handle them appropriately in our app code.

--

--

Danny Smith

Helping companies become high-performance remote organisations. Currently working with @HeyOyster . Used to write code. Occasional blues musician.