• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Rapid Blog

  • Enterprise
  • API Hub
  • Add Your API
  • About
  • Docs
    • API Glossary
  • Blog
    • What is an API?
    • REST API Tutorials
    • Most Popular APIs
  • Sign Up
    • Log In
Blog » API Testing » How to Test an API with Ruby

How to Test an API with Ruby

By Team RapidAPI // January 4, 2021

If you’ve read some of our articles on this site, you might’ve noticed some (if not all) skip writing tests for the code we publish. This is only because there’s so much you can write in an article before it turns into an essay. It’s important to note that writing tests for your code is extremely important. When you’re just playing around with something, writing some proof-of-concept, or something similarly simple, skipping tests might be acceptable. But once your project starts turning into something bigger, where stability is important, writing tests is crucial. In this article, we’d like to go through the different approaches to testing APIs in Ruby, from unit tests to integration tests. We will of course not be able to cover every single way of testing using Ruby, but this should give you a good introduction to the world of testing.

What is Testing?

Testing is, kind of like the word describes, writing code that will test your code. For example, if you write an endpoint for your API, and you want to make sure it does what you expect, you could manually test it (using cURL in the command line, for instance). This is totally fine, and actually expected when you’re just writing the endpoint for the first time, but eventually, you’ll want to automate this. What happens, for example, if you write another endpoint, which drives you to modify something the first endpoint depended on? You could accidentally break the first endpoint. You could, again, manually test every endpoint every time you make a change. What about edge cases? That is, what happens if the user sends some funky data? Can your endpoint handle that? You can see how the list of cases starts piling on, and manually testing every single case every time you want to add or change code will get tedious and time-consuming.

The solution to this problem is to automate your tests. This is what code testing is: writing down all of these test cases so code will test for you. Every time you write a new endpoint, you write test cases to make sure everything works as expected. So the next time you add a new endpoint or modify an existing one, you can be sure (and quickly so) that you didn’t break anything, because your automated tests will tell you if something is behaving unexpectedly. Every time you find a bug, you can write a test to make sure it never appears again.

What types of tests are there?

Your tests are, of course, only as good as what you write. You have to make sure you cover all (or at least most) of the cases, to make sure introducing bugs is as difficult as possible. For this purpose, there are tons of different testing paradigms, frameworks, and libraries. You’re in charge of picking whatever is best for your use case. Ruby on Rails, for example, comes with a predefined set of tests to help you get started, and they should cover most of what a Rails application would need. It’s a combination of unit tests and integration tests.

Unit Tests

Unit tests are defined as tests that will only encompass a very specific unit of code (a function, for example). They will test input and output. You would usually write these out as you’re writing the functions, to make sure they behave as expected. You would also make sure you catch corner cases.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def add(left, right)
left + right
end
RSpec.describe 'add' do
it 'adds' do
expect(add(1, 2)).to eq(3)
end
it 'handles negative numbers' do
expect(add(-1, -2)).to eq(-3)
end
it 'handles zeroes' do
expect(add(100, 0)).to eq(100)
end
end
def add(left, right) left + right end RSpec.describe 'add' do it 'adds' do expect(add(1, 2)).to eq(3) end it 'handles negative numbers' do expect(add(-1, -2)).to eq(-3) end it 'handles zeroes' do expect(add(100, 0)).to eq(100) end end
def add(left, right)
  left + right
end

RSpec.describe 'add' do
  it 'adds' do
    expect(add(1, 2)).to eq(3)
  end

  it 'handles negative numbers' do
    expect(add(-1, -2)).to eq(-3)
  end

  it 'handles zeroes' do
    expect(add(100, 0)).to eq(100)
  end
end

This very crude example shows how you would write some example cases for the add method. A more real example should test all reasonable corner cases as well.

Integration Tests

Integration tests take it a step further. As the name implies, they test how different components in your program interact and integrate with each other. Unit tests alone cannot test that, and without integration tests, it would be easy to call one function from another function with incorrect parameters. Integration testing would catch mistakes like this.

How to test an API with Ruby

We’d like to show you how to get started with testing your apps. This will, of course, strongly depend on what you’ve written, which frameworks you’ve used, etc., but it should always be possible to write tests to make sure you’re writing stable code. For Ruby, there are tons of testing frameworks to choose from. Some of them are based on specific principles of writing tests. For, example, MiniTest, a small and fast framework, focuses on letting you write simple, readable, and predictable tests. RSpec, on the other hand, is more of a hands-off framework that gives you many tools to write tests however suits you best. They are both great frameworks and work very well, and it’s just a matter of trying them both to see which one you like best.

For this article, we will be focusing on RSpec, but keep in mind most of what you’ll learn here applies to all testing frameworks. You will need to have Ruby installed for this. Follow the official installation instructions to get started, if you don’t already have it installed in your system. We will also be using Rails as a starting point since it helps you get started by generating a bunch of tests for you (or at least the bare minimum). Make sure you install Rails by running gem install rails on your terminal.

Step 1: Generate a new project

We’re going to be building a simple blog API, which has a Post model and some endpoints to manage them. You can later extrapolate what you learn here to add more models and endpoints. Generate our new project by running this on your terminal:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
rails new blog --api --skip-test
rails new blog --api --skip-test
rails new blog --api --skip-test

Since we’re only focusing on building an API, we’re using the --api modifier, to skip unnecessary libraries for the frontend. We also skipped installing tests, since we’re going to use RSpec for them. If you’re wondering why we’re choosing RSpec over Rails’ built-in test framework, it’s because we believe RSpec will allow you to use the knowledge you learn here to write tests for other non-Rails projects. This doesn’t mean you can’t use other frameworks for testing, of course. To install RSpec, we’re going to use the rspec-rails gem, which simplifies the installation process. Add the gem to the Gemfile first:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails', '~> 4.0.1'
end
group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 4.0.1' end
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.1'
end

Make sure you add the gem in the development and test group, otherwise it won’t work correctly. After that, run bundle install in your terminal, followed by rails generate rspec:install to finish. This last command will create a couple of files and folders. You should then be good to go.

Step 2: Create our model

Our blog API needs posts. For this, we’ll create a model to hold them. This will be a simple model, where we’ll have some validations. We’ll also take the opportunity to run the scaffold generator, which will generate most of the endpoints for our model in one go. Run rails generate scaffold Post title:string body:text. You should see something like this as the output:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
invoke active_record
create db/migrate/20201218135605_create_posts.rb
create app/models/post.rb
invoke rspec
create spec/models/post_spec.rb
invoke resource_route
route resources :posts
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke resource_route
invoke rspec
create spec/requests/posts_spec.rb
create spec/routing/posts_routing_spec.rb
invoke active_record create db/migrate/20201218135605_create_posts.rb create app/models/post.rb invoke rspec create spec/models/post_spec.rb invoke resource_route route resources :posts invoke scaffold_controller create app/controllers/posts_controller.rb invoke resource_route invoke rspec create spec/requests/posts_spec.rb create spec/routing/posts_routing_spec.rb
invoke  active_record
create    db/migrate/20201218135605_create_posts.rb
create    app/models/post.rb
invoke    rspec
create      spec/models/post_spec.rb
invoke  resource_route
 route    resources :posts
invoke  scaffold_controller
create    app/controllers/posts_controller.rb
invoke    resource_route
invoke    rspec
create      spec/requests/posts_spec.rb
create      spec/routing/posts_routing_spec.rb

As you can see, not only did the command generate our controller and routes, it also generated some test files for us. Some of these files even have tests written out for us, while some are mostly blank. Let’s focus on the model first, by adding some validation rules:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# app/models/post.rb
class Post < ApplicationRecord
validates :title, :body, presence: true
validates :title, length: { within: 5..50 }
end
# app/models/post.rb class Post < ApplicationRecord validates :title, :body, presence: true validates :title, length: { within: 5..50 } end
# app/models/post.rb
class Post < ApplicationRecord
  validates :title, :body, presence: true
  validates :title, length: { within: 5..50 }
end

We just added some basic validation rules to our Post model. These make sure a post always has a title and a body, while also limiting the title’s length to be at least 5 characters and less than 50 characters (this is totally arbitrary and only for illustration purposes). Now, edit the model’s unit test file so it looks like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
require 'rails_helper'
RSpec.describe Post, type: :model do
context 'validations' do
it 'accepts a valid post' do
post = Post.new(title: 'A decent title', body: 'Some body')
expect(post.save).to be(true)
end
it 'validates presence of title' do
post = Post.new(body: 'Some body')
expect(post.save).to be(false)
end
it 'validates length of title' do
post = Post.new(title: 'A' * 51, body: 'Some body')
expect(post.save).to be(false)
end
it 'validates presence of body' do
post = Post.new(title: 'A decent title')
expect(post.save).to be(false)
end
end
end
require 'rails_helper' RSpec.describe Post, type: :model do context 'validations' do it 'accepts a valid post' do post = Post.new(title: 'A decent title', body: 'Some body') expect(post.save).to be(true) end it 'validates presence of title' do post = Post.new(body: 'Some body') expect(post.save).to be(false) end it 'validates length of title' do post = Post.new(title: 'A' * 51, body: 'Some body') expect(post.save).to be(false) end it 'validates presence of body' do post = Post.new(title: 'A decent title') expect(post.save).to be(false) end end end
require 'rails_helper'

RSpec.describe Post, type: :model do
  context 'validations' do
    it 'accepts a valid post' do
      post = Post.new(title: 'A decent title', body: 'Some body')

      expect(post.save).to be(true)
    end

    it 'validates presence of title' do
      post = Post.new(body: 'Some body')

      expect(post.save).to be(false)
    end

    it 'validates length of title' do
      post = Post.new(title: 'A' * 51, body: 'Some body')

      expect(post.save).to be(false)
    end

    it 'validates presence of body' do
      post = Post.new(title: 'A decent title')

      expect(post.save).to be(false)
    end
  end
end

We’ve simply added some examples to test all validations. We first test we can actually save a correct model, then we test all validation rules to make sure they’re actually validating. The context keyword allows you to group specs depending on what they test. In this case, we’re testing validation rules, so it makes sense to group them. Go ahead and run these tests by running bundle exec rspec spec/models in your terminal:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
....
Finished in 0.02816 seconds (files took 1.32 seconds to load)
4 examples, 0 failures
.... Finished in 0.02816 seconds (files took 1.32 seconds to load) 4 examples, 0 failures
....

Finished in 0.02816 seconds (files took 1.32 seconds to load)
4 examples, 0 failures

Each little dot shows a successful test. Did you notice something missing in our tests? Remember that we specified a title should be at least 5 characters, but we don’t have any example testing that. Let’s add that:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
it 'validates a title is not too short' do
post = Post.new(title: 'Hi', body: 'Some body')
expect(post.save).to be(false)
end
it 'validates a title is not too short' do post = Post.new(title: 'Hi', body: 'Some body') expect(post.save).to be(false) end
it 'validates a title is not too short' do
  post = Post.new(title: 'Hi', body: 'Some body')

  expect(post.save).to be(false)
end

And run your tests again. You should still see success all around. What happens when a test fails though? Let’s try that. Modify your model’s validations so the length reads within: 0..50. This should mean the test we just added will fail. Try it:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...F.
Failures:
1) Post validations validates a title is not too short
Failure/Error: expect(post.save).to be(false)
expected false
got true
# ./spec/models/post_spec.rb:26:in `block (3 levels) in <top (required)>'
Finished in 0.0588 seconds (files took 1.24 seconds to load)
5 examples, 1 failure
Failed examples:
rspec ./spec/models/post_spec.rb:23 # Post validations validates a title is not too short
...F. Failures: 1) Post validations validates a title is not too short Failure/Error: expect(post.save).to be(false) expected false got true # ./spec/models/post_spec.rb:26:in `block (3 levels) in <top (required)>' Finished in 0.0588 seconds (files took 1.24 seconds to load) 5 examples, 1 failure Failed examples: rspec ./spec/models/post_spec.rb:23 # Post validations validates a title is not too short
...F.

Failures:

  1) Post validations validates a title is not too short
     Failure/Error: expect(post.save).to be(false)
     
       expected false
            got true
     # ./spec/models/post_spec.rb:26:in `block (3 levels) in <top (required)>'

Finished in 0.0588 seconds (files took 1.24 seconds to load)
5 examples, 1 failure

Failed examples:

rspec ./spec/models/post_spec.rb:23 # Post validations validates a title is not too short

The example fails, as expected.

What we just did is write unit tests. These test single units of code (in this case validations). Any methods you might later add to this model would also need to be tested here to make sure they behave as expected. For example, if we add a slug method, which turns the title into a more URL-friendly string, could look like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
def slug
title.parameterize
end
def slug title.parameterize end
def slug
  title.parameterize
end

And the corresponding test:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
describe '#slug' do
it 'converts to url-friendly string' do
post = Post.new(title: 'This is a whacky string & text', body: 'body')
expect(post.slug).to eq('this-is-a-whacky-string-text')
end
end
describe '#slug' do it 'converts to url-friendly string' do post = Post.new(title: 'This is a whacky string & text', body: 'body') expect(post.slug).to eq('this-is-a-whacky-string-text') end end
describe '#slug' do
  it 'converts to url-friendly string' do
    post = Post.new(title: 'This is a whacky string & text', body: 'body')

    expect(post.slug).to eq('this-is-a-whacky-string-text')
  end
end

A couple of things to note here. First, we’re using describe '#slug' to write our examples. This is a common practice, where we “describe” what the #slug method does, or how it behaves. Second, we’re not writing many examples, because our method delegates the conversion of our title to a slug to Rails’ parameterize method, which we can assume is thoroughly tested in Rails itself. In case we had written our own logic, it would make a lot of sense to include a bunch of extra examples and edge-cases.

Step 3: Other tests

Rails generated a bunch of other tests when we generated the scaffold for our posts. Let’s go over them to see what they’re testing, and adapt the ones that need some changes. The first one Rails generates is one for routing. You can consider this unit testing for your routes.rb file, where we make sure specific paths get routed to the controller and method we want, passing the parameters we expect. Let’s take a look at the posts_routing_spec.rb file. The examples should be pretty straightforward, where we expect a certain path to be routed to a certain method:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
it "routes to #update via PATCH" do
expect(patch: "/posts/1").to route_to("posts#update", id: "1")
end
it "routes to #update via PATCH" do expect(patch: "/posts/1").to route_to("posts#update", id: "1") end
it "routes to #update via PATCH" do
  expect(patch: "/posts/1").to route_to("posts#update", id: "1")
end

This tests that a PATCH request to /posts/1 is routed to the Posts controller’s update method, with the parameter id set to 1. More complex routing might require more intricate examples.

Another batch of tests Rails generated for us is the “requests” test for our Post scaffold. You can consider these integration specs since they test the results of API requests. In these, we’re really testing what happens from the moment we make a request, to the response and changes in the database that are triggered by it. Check out posts_spec.rb. You’ll notice the file is pretty well described in the header, and that we’re supposed to fill out some blanks in order to make it work. Let’s wait on that a bit. First, take a look at the examples and what they test:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
describe "GET /show" do
it "renders a successful response" do
post = Post.create! valid_attributes
get post_url(post), as: :json
expect(response).to be_successful
end
end
describe "GET /show" do it "renders a successful response" do post = Post.create! valid_attributes get post_url(post), as: :json expect(response).to be_successful end end
describe "GET /show" do
  it "renders a successful response" do
    post = Post.create! valid_attributes
    get post_url(post), as: :json
    expect(response).to be_successful
  end
end

This, albeit a very simplified example, first creates a post in the database with valid attributes and then tests that GETing that post doesn’t yield an error. Ideally, we should add an extra example making sure the actual JSON response returns what we expect. We’ll get to that in a bit. Check out this other example in the same file:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
describe "PATCH /update" do
context "with valid parameters" do
let(:new_attributes) {
skip("Add a hash of attributes valid for your model")
}
it "updates the requested post" do
post = Post.create! valid_attributes
patch post_url(post),
params: { post: invalid_attributes }, headers: valid_headers, as: :json
post.reload
skip("Add assertions for updated state")
end
it "renders a JSON response with the post" do
post = Post.create! valid_attributes
patch post_url(post),
params: { post: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq("application/json")
end
end
context "with invalid parameters" do
it "renders a JSON response with errors for the post" do
post = Post.create! valid_attributes
patch post_url(post),
params: { post: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq("application/json")
end
end
end
describe "PATCH /update" do context "with valid parameters" do let(:new_attributes) { skip("Add a hash of attributes valid for your model") } it "updates the requested post" do post = Post.create! valid_attributes patch post_url(post), params: { post: invalid_attributes }, headers: valid_headers, as: :json post.reload skip("Add assertions for updated state") end it "renders a JSON response with the post" do post = Post.create! valid_attributes patch post_url(post), params: { post: invalid_attributes }, headers: valid_headers, as: :json expect(response).to have_http_status(:ok) expect(response.content_type).to eq("application/json") end end context "with invalid parameters" do it "renders a JSON response with errors for the post" do post = Post.create! valid_attributes patch post_url(post), params: { post: invalid_attributes }, headers: valid_headers, as: :json expect(response).to have_http_status(:unprocessable_entity) expect(response.content_type).to eq("application/json") end end end
describe "PATCH /update" do
  context "with valid parameters" do
    let(:new_attributes) {
      skip("Add a hash of attributes valid for your model")
    }

    it "updates the requested post" do
      post = Post.create! valid_attributes
      patch post_url(post),
            params: { post: invalid_attributes }, headers: valid_headers, as: :json
      post.reload
      skip("Add assertions for updated state")
    end

    it "renders a JSON response with the post" do
      post = Post.create! valid_attributes
      patch post_url(post),
            params: { post: invalid_attributes }, headers: valid_headers, as: :json
      expect(response).to have_http_status(:ok)
      expect(response.content_type).to eq("application/json")
    end
  end

  context "with invalid parameters" do
    it "renders a JSON response with errors for the post" do
      post = Post.create! valid_attributes
      patch post_url(post),
            params: { post: invalid_attributes }, headers: valid_headers, as: :json
      expect(response).to have_http_status(:unprocessable_entity)
      expect(response.content_type).to eq("application/json")
    end
  end
end

This tests updates to a Post. Notice there are two contexts: one for valid parameters and one for invalid. You’re not necessarily supposed to write tests like this, but it’s a good idea since it helps organize the file. Also, notice how the examples are not complete: we’re supposed to add some new attributes and assertions. Let’s go over these tasks now so the examples work. First, let’s update the example attributes wherever there’s a “skip” method call. There’s three of those:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let(:valid_attributes) {
{
title: 'Some valid title',
body: 'Lorem ipsum.'
}
}
let(:invalid_attributes) {
# Too short title
{
title: 'X'
}
}
# ...
let(:new_attributes) {
{
title: 'An edited title',
body: 'An edited body'
}
}
let(:valid_attributes) { { title: 'Some valid title', body: 'Lorem ipsum.' } } let(:invalid_attributes) { # Too short title { title: 'X' } } # ... let(:new_attributes) { { title: 'An edited title', body: 'An edited body' } }
let(:valid_attributes) {
  {
    title: 'Some valid title',
    body: 'Lorem ipsum.'
  }
}

let(:invalid_attributes) {
  # Too short title
  {
    title: 'X'
  }
}

# ...

let(:new_attributes) {
  {
    title: 'An edited title',
    body: 'An edited body'
  }
}

Now, if you read those examples carefully, you might notice that, at least at the time of writing this article, there’s a bug in the generated examples, wherein the PATCH tests they use invalid_attributes instead of the new_attributes. You might not bump into this. Make sure you fix that, otherwise your tests will never succeed! You’ll also notice if you run the specs (using bundle exec rspec spec/requests), that some expectations fail:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
1) /posts POST /create with invalid parameters renders a JSON response with errors for the new post
Failure/Error: expect(response.content_type).to eq("application/json")
expected: "application/json"
got: "application/json; charset=utf-8"
(compared using ==)
1) /posts POST /create with invalid parameters renders a JSON response with errors for the new post Failure/Error: expect(response.content_type).to eq("application/json") expected: "application/json" got: "application/json; charset=utf-8" (compared using ==)
1) /posts POST /create with invalid parameters renders a JSON response with errors for the new post
   Failure/Error: expect(response.content_type).to eq("application/json")
   
     expected: "application/json"
          got: "application/json; charset=utf-8"
   
     (compared using ==)

You should replace those expectations with something like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
expect(response.content_type).to match(a_string_including("application/json"))
expect(response.content_type).to match(a_string_including("application/json"))
expect(response.content_type).to match(a_string_including("application/json"))

We should also add some expectations to the PATCH examples, to make sure editions work:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
it "updates the requested post" do
post = Post.create! valid_attributes
patch post_url(post),
params: { post: new_attributes }, headers: valid_headers, as: :json
post.reload
expect(post.title).to eq('An edited title')
expect(post.body).to eq('An edited body')
end
it "updates the requested post" do post = Post.create! valid_attributes patch post_url(post), params: { post: new_attributes }, headers: valid_headers, as: :json post.reload expect(post.title).to eq('An edited title') expect(post.body).to eq('An edited body') end
it "updates the requested post" do
  post = Post.create! valid_attributes
  patch post_url(post),
        params: { post: new_attributes }, headers: valid_headers, as: :json
  post.reload

  expect(post.title).to eq('An edited title')
  expect(post.body).to eq('An edited body')
end

Noticed the two last expectations. They test that the endpoint actually edits the post. We should also show you how you can test the JSON response of your API, by modifying the example for the GET /posts/1 endpoint, as we mentioned before:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
describe "GET /show" do
it "renders a successful response" do
post = Post.create! valid_attributes
get post_url(post), as: :json
expect(response).to be_successful
json = JSON.parse(response.body)
expect(json['title']).to eq('Some valid title')
expect(json['body']).to eq('Lorem ipsum.')
end
end
describe "GET /show" do it "renders a successful response" do post = Post.create! valid_attributes get post_url(post), as: :json expect(response).to be_successful json = JSON.parse(response.body) expect(json['title']).to eq('Some valid title') expect(json['body']).to eq('Lorem ipsum.') end end
describe "GET /show" do
  it "renders a successful response" do
    post = Post.create! valid_attributes
    get post_url(post), as: :json
    expect(response).to be_successful

    json = JSON.parse(response.body)

    expect(json['title']).to eq('Some valid title')
    expect(json['body']).to eq('Lorem ipsum.')
  end
end

If you run the specs now, they should all pass. Otherwise, check out the errors and try to understand what’s going on. Remember that the generated specs are only a template, and you should build on top of this for proper test coverage.

RapidAPI Testing

Like we mentioned at the beginning of the article, there are many ways of testing APIs, and many purposes for each one. RapidAPI provides a new service called RapidAPI Testing, which enables you to run something similar to the request tests we just covered. One of the advantages of using RapidAPI Testing is that it enables you to monitor your API by running the tests from different geographical locations, giving you great insight into your API’s performance and stability.

Conclusion

We hope this article gave you a good starting point on how testing works, and how you can leverage it for your Ruby and Ruby on Rails APIs. Testing of applications is something we’d strongly encourage, since the time invested in writing a good test suite far outweighs the time lost tracking down bugs, changes, and regressions from the lack of proper testing.

5/5 - (2 votes)
« What is API Management?
Top 4 Apigee Alternatives for API Management »

Filed Under: API Testing, Ruby API Tutorials Tagged With: api testing, ruby, ruby on rails, testing

Team RapidAPI

Reader Interactions

Leave a Reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Build anything with APIs, faster.

Discover, evaluate, and integrate with any API. RapidAPI is the world’s largest API Hub with over 4 Million developers and 35,000 APIs.

Browse APIs »

APIs mentioned in this article

Try RapidAPI Testing
Try RapidAPI Testing

Footer

  • API Guides
  • API Courses
  • API Glossary
  • API Testing
  • API Management
  • Most Popular APIs
  • Free APIs List
  • How to use an API
  • Learn REST API
  • Build API’s
  • About
  • Build APIs
  • Careers
  • Contact Us
  • Write for Us
  • API Directory
  • Press Room
  • Privacy Policy
  • Terms of Use

© 2025 RapidAPI. All rights reserved.

Building an Enterprise API Program
Learn More

×