API tests in the repository? It can be done with HttpClient!
Tags: ruby, rails, testing, productivity
Published: 2022-02-09 06:32:55

If you create JSON API, you probably know by heart the support for tools such as Postman, Insomnia, Curl. However, when querying with them, it is not possible to store API tests in a repository and manage them with version control. I also thought it was impossible until I found this [video](https://www.youtube.com/watch?v=n8KCuKhDSZY). JetBrains tools have a built-in ingenious plugin - HttpClient. In this post, I have prepared for you a short demonstration of its capabilities using Ruby Mine and Ruby on Rails. API tests in the repository? Can be! Very much!

As a demonstration environment I will use a simple application written in Ruby on Rails. It took me 7 minutes to create this simple API with simulated authorization! I was timing myself on purpose. That's why I love RoR! But to the point.

The application has a simple structure. The main actor is the user who can own books and cars. Collector. Let's say it's such a typical directory application. Simply put.

##I created the data structure with the following migrations.


![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c7vfoocuabudu4hoq78f.png)

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5kjds65pdz4b39b5j2ma.png)


![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvp3fnj4p45wf5pituqf.png)

##Model definition:

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sj9t3sac4qdg9ze2e48o.png)

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7hrfjh4ed5448k84fatu.png)

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wio6xvaqhr7ri4m2cwlz.png)

##And controllers.


![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8v3r8mzchmpni98y9a2.png)

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7k4cmvghohnhph9ydzl4.png)

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wmkfi8x51tnvvbqvn0gm.png)

##Routing:

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3gl2vvhlgnv5grhbdct.png)

##And `ApplicationController`, into which I put practically all the logic.

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpbiakkdwcshdo4a0hio.png)

In API we can:

- Check if the application is running (`home` action).
- Download all books of a given user from the database.
- Download all cars of a given user from the database.
- Download a list of all users in the database.
- Log in to the application and obtain an authorization token

Access to specific user data is secured with a token that should be provided in the `Authorization` header.

Before starting, I created a few users, a few books and a few cars in the database.

We start our adventure with HttpClient. Just create a file with the `.http` extension and RubyMine will do the rest and adjust the interface to fire queries.

I have created the `api_test.http` file.

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjdecvzr30sc52xsyiqg.png)

First requests. I check if the API works. One line is enough:

```javascript 
GET http://localhost:3000
```

And the result:

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awm4ezbe225mxbshlnfx.png)

Okay, but it probably won't end with one request. Fortunately, I don't have to enter the address in subsequent queries every time, what's more, I can have addresses configured for different environments and run my client in one of them.

I add the `http-client.env.json` file in which I set the environment and the `url` variable.

```javascript
{
  "development": {
    "url": "http://localhost:3000"
  }
}
```

And now I can use a variable instead of a patched url. The IDE tells me everything beautifully.

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2m1nh2growh1dqk4cwty.png)

We separate subsequent queries with three hashes: `###`

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gnga5gzryck0cyj8hav.png)

##It's time to log in

I am adding a new request, this time of the POST type. See how easy it is to define headers and parameters.

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/409zk58rzgmo6a6zlz2m.png)

Authorization was successful and I got an `auth_token` in response. Now it's time to capture it, assign it to a variable, and use it in subsequent queries. This is done in the code that we put in braces with the percentage `{%%}`, which is just **JavaScript**.

```javascript
POST{{url}}/login
Accept: application/json
Content-Type: application/json

{
  "email": "user1@email.com",
  "password": "password"
}


> {%
  auth_token = response.body['auth_token']
  client.global.set("token", auth_token)
%}

###
GEThttp://{{url}}/users/1
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{token}}
```

We can now authorize our inquiries with a token:

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upgvkbq8alyzkpcekcy3.png)

HttpClient also has something for test fans. You can write automated tests for your queries! These tests are run together with queries, and their results are visible in the IDE runner.

```javascript
###
GEThttp://{{url}}/users/1
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{token}}

> {%
 client.test("Get User",function() {
   client.assert(response.body['books_count'] === 5, "Books count returned is wrong")
 })

 client.test("Status",function() {
   client.assert(response.status === 200, "Response status is not 200")
 })
 %}
```

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/123mk6rvnyxz7yuvlz24.png)

##What now? Git commit, git push. And we have versioned tests of our API.

![TestAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otch0lp4o9anegesy1p2.gif)

You can find the repository with the above code [here](https://github.com/rafpiek/httpclient-rubymine-sample).