How to write tests with RSpecApi
RSpecApi extends the DSL provided by RSpec with the following methods:
resourcedescribes a RESTful API resourceget,post,put,patch, anddeleteindicate the actions available on the resourcerespond_withsends a request to the API and verifies that the response meets the expectationshas_attributelists the expected attributes in the response bodyacceptallows to make parametrized requests for filters, sorting, pagination and callbackshostandadapterspecify how to access the API, either locally or remotelyauthorize_withprovides authentication credentials to the requestthrottleprevents ‘Too Many Requests’ errors
The next example introduced on Page 1 will be the starting point to illustrate these methods and how to use them:
concerts_spec.rbresource :concert do
host 'http://myconcerts.herokuapp.com'
has_attribute :id, type: {number: :integer}
has_attribute :where, type: :string
has_attribute :website, type: [:null, string: :url]
get '/concerts', collection: true do
respond_with :ok
end
post '/concerts' do
respond_with :created, concert: {where: 'Coachella'}
respond_with :unprocessable_entity, concert: {where: nil}
end
end
resource
RSpecApi makes some assumptions on the web APIs to be tested, based on a set of popular best practices.
The first assumption is that the API should follow the key principles of REST, which
“… involve separating your API into logical resources. These resources are manipulated using HTTP requests where the method (GET, POST, PUT, PATCH, DELETE) has specific meaning.”
The method resource helps separate API tests by resource, as in:
resource :concert do
# Here list the actions to access a concert resource
# e.g. get '/concerts', post '/concerts', delete '/concerts/:id'
end
resource :artist do
# Here list the actions to access an artist resource
# e.g. patch '/artists/:id', get '/country/:country/artists'
end
There is not a lot of magic in this method: a look at its source code
reveals how it is mostly syntactic sugar around RSpec’s describe. The code above is indeed equivalent to:
describe "Concerts" do
extend RSpecApi::Resource
# Here list the actions to access a concert resource
# e.g. get '/concerts', post '/concerts', delete '/concerts/:id'
end
describe "Artists" do
extend RSpecApi::Resource
# Here list the actions to access an artist resource
# e.g. patch '/artists/:id', get '/country/:country/artists'
end
In short, resource creates an example group to describe an API resource,
and makes available inside that group the methods get, post, put, patch, and delete of RSpecApi::Resource
which are detailed hereafter.
get, post, put, patch, delete
The next best practice that RSpecApi expects from an API is that resources can be accessed with HTTP methods:
“Once you have your resources defined, you need to identify what actions apply to them and how those would map to your API. RESTful principles provide strategies to handle CRUD actions using HTTP methods […] GET, POST, PUT, PATCH, DELETE.”
The methods get, post, put, patch, and delete
help describe the actions available for each resource, as in:
resource :concert do
get '/concerts', collection: true do
# Here describe the expectations of GET /concerts
end
post '/concerts' do
# Here describe the expectations of POST /concerts
end
end
There is not a lot of magic in these methods either: a look at the source code
reveals how they are mostly syntactic sugar around RSpec’s describe. The code above is indeed equivalent to:
resource :concert do
describe "Retrieving a list of concerts", rspec_api_params: {action: :get, route: "/concerts", collection: true} do
extend RSpecApi::Requests
# Here describe the expectations of GET /concerts
end
describe "Creating one concert", rspec_api_params: {action: :post, route: "/concerts"} do
extend RSpecApi::Requests
# Here describe the expectations of POST /concerts
end
end
In short, get, post, put, patch, and delete
create example groups to describe actions to access API resources. Inside each example group:
- the description is automatically generated from the resource name and the action;
- the route, the action and any other optional argument are passed through using RSpec’s metadata;
- the method
respond_withofRSpecApi::Requestsis available, which is detailed hereafter.
respond_with
Coming soon…
has_attribute
Coming soon…
accept
Coming soon…
host, adapter
Coming soon…
authorize_with
Coming soon…
throttle
Coming soon…