API Client Gem Testing With Rspec and Capybara

Chris Voxland
Plated Engineering & Data Science
3 min readDec 3, 2018

Your team has been working towards a more service oriented architecture. The product team informs you that a feature request has been pushed through from somewhere on high. Millions of dollars in funding are at stake because one of your investors, whose name neither you, nor apparently he, can remember, absolutely NEEDS your application to be able to tell users whether or not their name is Steve. And they need it done soon.

Being the prudent developer that you are, you realize that this logic is isolated enough to live in its own application, and will give you the double victory of being able to pad your resume with another buzzword (Microservices! Aha!) and avoiding the three hour wait for your main application’s single, all-encompassing feature test to to finish flickering. You take a moment to remind yourself to finally buy that Arduino so that you can secretly connect your office’s lights to your CI service’s API and make everyone feel the pain of your sporadic test failures. Maybe then they’ll give you time to fix the flickers…

Decision made, you write your app, make sure you have 100% test coverage, get it deployed, and your masterpiece is complete. Steve Service lives! But it is useless in isolation, it must communicate with your other applications. Your stomach drops like Snoop Dogg’s freshly microwaved Hot Pocket in a moment of dread when you think of the other developers getting their grubby, malformed requests all over your pristine new Steve Service.

The solution strikes you: a client gem. Ostensibly you are making your fellow developers lives easier, giving them a way to quickly connect to your service without worrying about lower level implementation details and decoupling consumers from being affected by any downstream changes. You know the truth though; Steve Service must remain pure.

You set to work, TDDing the perfect API: intuitive, simple, secure, and impermeable to their taint. All is as it should be, now only to test it live. You begin making requests, then a thought strikes you: What happens if Steve Service changes?

You realize that you could introduce breaking changes to Steve Service (well not YOU obviously, but SOMEONE) and not know until after it hits a live server. That just won’t do…

Capybara to the Rescue

Testing API client gems in the applications they are built for is a great way to catch breaking changes in your services before they make it to production, and using Capybara to run a fully working test version of your app makes it trivially easy to do.

First, install the client gem in the application you want to test against:

group :development, :test do
gem "steve-service-client"
end

Next, initialize the server:

let(:server) do
Capybara::Server.new(SteveService::Application).boot
end

This server instance will expose the port that it has bound to. You will need to configure the client gem to hit `localhost` on said port in order for requests to actually hit the server (The port is selected automatically by Capybara):

before do
SteveServiceClient.configure do |config|
config.steve_service_url = "http://localhost:#{server.port}"
end
end

At this point, you are free to run tests with your client gem sending real requests to the application it is meant to interact with:

require "rails_helper"describe "SteveServiceClient gem" do
let(:server) do
Capybara::Server.new(SteveService::Application).boot
end
before do
SteveServiceClient.configure do |config|
config.steve_service_url = "http://localhost:#{server.port}"
end
end

it "returns true if your name is Steve" do
# This is hitting a running instance of SteveService, no stubs or mocks.
is_steve_response = SteveServiceClient.is_steve?("Steve")
expect(is_steve_response).to eq(true)
end
end

Testing your API client gems this way will help prevent breaking application changes from making it into production. You still need to be aware of breaking changes to the client itself though; they can easily sneak into production and break if they are not kept up to date and tested in the application they are meant to consume. A tool like Dependabot can help reduce the risk of this occurring.

You should now know how to test your API client gems against the services they are consuming, giving you much more confidence in the code you are shipping.

We love feedback here at Plated, so feel free to leave comments or questions!

--

--