Whether at you job or personal projects you would need at some point have to build you own API wrapper in ruby. Today, i decided to build my own Wrapper that i will turn into a gem in a later blog post. I want to do it methodically according to Test Driven Development principles.
It is always a hassle to test API calls but there is a way on how it should be done and we will talk about it later on.
I picked the WMATA API because it is well written and well documented. As you can see in their developer website each call has a json response example. We will use these to test our code against it later.
Let’s talk about our goal. I want to be able to set my api key and then make an api call in this manner:
1 2 |
|
Now, that i know what i want, let’s set up our TDD environment. The initial repository tree would look like this:
1 2 3 4 5 6 |
|
Let’s take a look at the Gemfile
and see what are the tools we are going to use:
1 2 3 4 5 |
|
Now that we have all the necessary gems do a bundle install
. Let’s take a look at the spec/spec_helper.rb
:
1 2 3 4 5 6 7 8 9 10 |
|
This is where it get’s tricky. If you rely on the API, your tests are not really tests, because they depend on the status of the API. If you have no internet, those tests will not work. Your tests should only test your own code, not the response of the API. We are using webmock to return to each call made to https://api.wmata.com/StationPrediction.svc/json/GetPrediction/
the json response in next_trains.json
. This response is the expected result provided by the documentation here
So let’s add the file next_trains.json
in spec/fixtures/next_trains.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
We have everything setup now let’s write our first test in spec/train_spec.rb
.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Notice that the api key does not have to be real because the call to the live api will not be made. It will be mocked and will return the expected json response.
Let’s create the module that will handle the API calls in lib/wamta.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Good, now we have a module that will create a client object when an api_key is passed and if we want to call next_trains
without setting up the api key it will throw an exception “please set the api key”. Now, let’s create the Client class in lib/client.rb
that will actually handle the API calls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
When you run the tests now, everything should be green. This part makes sure that our code handles correctly the expected response, now let’s make a live API call :
1 2 |
|
It should return an array of all the next trains for the specified station. Now that it is working we can do the same for all the other api calls