---
title: Rest API Testing with JMeter (Step by Step Guide)
url: https://blog.octoperf.com/rest-api-testing-with-jmeter-step-by-step-guide/
date: '2018-04-23'
authors:
- jloisel
categories:
- JMeter
tags:
- JMeter
- REST
- JSON
- JSONPath
- Assertion
- Plugins
description: Learn how to load test a Json Rest API using JMeter by handling authentication headers, extracting variables from Json responses and applying Json assertions. Includes a sample JMX project.
---

# Rest API Testing with JMeter (Step by Step Guide)

I'm sure you're here because **you need to load test a Json Rest API**. It's not a surprise since [Rest API](https://fr.wikipedia.org/wiki/Representational_state_transfer) are increasingly popular these days.

That's the purpose of this guide: help you **load test** a [Json](https://www.json.org/json-en.html) Rest API **through a concrete example**, [OctoPerf's Json Rest API](https://api.octoperf.com/swagger-ui/index.html).

And this guide will completely get you through the following knowledge:

- Handle **Rest API Login** using an [Http POST Request](https://en.wikipedia.org/wiki/POST_(HTTP)),
- [Extract Variables from a Json Response](https://blog.octoperf.com/how-to-extract-data-from-json-response-using-jmeter/) and reuse it later in the script,
- And verify Json responses using [JMeter Json Assertion](https://blog.octoperf.com/jmeter-assertions-the-ultimate-guide/#json-assertion) (introduced in [JMeter 4](https://jmeter.apache.org/)).

**No theory here, only practice**: everything is based on a **realistic Rest API** (not a dummy example). You can [download the sample JMX](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-rest-api.jmx) while following the tutorial.

Ready to learn? Let's go!


## Rest API Login

[OctoPerf](https://api.octoperf.com/ui/) platform is based on a **Json Rest API**. We're going to see how you can simulate a **login to our API using JMeter**.

But how does the authentication works? How can we **simulate a login with JMeter**? Most Rest APIs work with the following **login workflow**:

1. **Login using an HTTP POST Request** by providing `username` and `password`,
2. **Receive a temporary authentication token** for later requests to identify yourself,
3. **Send the auth token** within subsequent requests, typically via [HTTP Headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) like `Authorization: Bearer AUTH_TOKEN`.

So does the OctoPerf API. That's pretty close to [Oauth Authentication](https://tools.ietf.org/html/rfc6750).

### Login API Specs

First, let's see how we can login on [OctoPerf Application](https://api.octoperf.com/ui/). Thankfully, our API has a [Swagger Specification](https://api.octoperf.com/swagger-ui/index.html): [Swagger](https://swagger.io) is a tool for providing a **Rest API Documentation**.

![Login Swagger Spec](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/login-swagger-specs.png "Doc specifying how to login via OctoPerf's API")

Good! Now let's examine the request we need to forge using JMeter:

- **Http Method**: must be a *POST* request, with some post parameters, (see [GET vs POST](https://www.w3schools.com/tags/ref_httpmethods.asp))
- **Http Scheme**: `https` since our Rest API is [secured by SSL](https://www.digicert.com/ssl/),
- **Hostname**: `api.octoperf.com`,
- **Path**: `/public/users/login` (Login endpoint path),
- **Post Parameters**:

  - **username**: the account username, if you don't have any you can easily [signup here](https://api.octoperf.com/ui/),
  - **password**: the associated password.

We should then receive from the server a **Json Response** which should look like:

```json
{
  "token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

See the token here? That's something we'll use later to identify ourselves on the Rest API. But, first let's take a look at the [JMeter HTTP Request](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request).

### Executing Login

![Login HTTP Request](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-rest-api-login.png "Login on OctoPerf via the Rest API")

Here we have our **Login Http Request** ready to be sent to our servers. I've just hidden the sensitive information, but that's basically your account information here. In order to **debug the login**, we're going to use the [View Results Tree Listener](https://blog.octoperf.com/jmeter-result-analysis-the-ultimate-guide/#view-results-tree).

![Login HTTP Request](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-rest-api-login-request.png "Login request sent to the server")

As we can see, the sent request is a [POST form-urlencoded](https://en.wikipedia.org/wiki/POST_(HTTP)) which contains our login and passwords. Nothing difficult here! Now, we're interested in the **Json Response** sent by the server.

![Login HTTP Response](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-rest-api-login-response.png "Response received from the server")

Fine! Now we've received the **Authentication Token**, we can extract it to reuse it in subsequent requests.

## Extracting Auth Token

[Token Based Authentication](https://www.w3.org/2001/sw/Europe/events/foaf-galway/papers/fp/token_based_authentication/) is a simple mechanism where a token **uniquely identifies a user session**. We need to handle this `dynamic parameter` to properly simulate a user interacting with our **Json API**.

### Using Json Extractor

To **extract the authentication token** from the server response, we're going to use [JMeter JsonPath Extractor](https://blog.octoperf.com/how-to-extract-data-from-json-response-using-jmeter/). The process of extracting a variable from a response works as follows:

1. The server sends back a response to our login request,
2. A [post-processor](https://jmeter.apache.org/usermanual/component_reference.html#postprocessors), like the **JsonPath Extractor** is executed afterwards,
3. the extractor *extracts part of the server response* and put it into a variable like `${token}`.

![JMeter Json Extractor](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-extractor.png "Extracting Authentication Token from server response")

We have configured the **JMeter Json Extractor** with those settings:

- **Name of created variables**: `token`, which will result in a reusable variable with the syntax `${token}`,
- **Json Path Expressions**: `$.token`, Refer to [Example JsonPath Expressions](https://blog.octoperf.com/how-to-extract-data-from-json-response-using-jmeter/#example-json-paths) for more info,
- And **Match Nr**: simply `1`, for the first occurence. But we could leave it blank.

See where I placed the extractor? Right under the `login` HTTP request. Let's also add a [Debug Sampler](https://jmeter.apache.org/usermanual/component_reference.html#Debug_Sampler) to see if the variable is extracted correctly.

### Enabling Debug

![JMeter Debug Sampler](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-debug-sampler.png "Enabling JMeter variables in Debug Sampler")

By setting *JMeter Variables* to `true`, we enable the sampler to **output the variables** during the test run. 

### Testing the Extraction

![JMeter Debug Sampler Result](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-debug-sampler-result.png "Token is successfully extracted from server response using Json Extractor")

Great! The Json extractor is **perfectly working**. It extracts the value of the `token` field from the Json response. We can now use the `${token}` expression in subsequent requests to perform **authenticated requests**.

Let's see how we reuse this token to tell our Rest API that we're a given user.

## Reinjecting Auth Token

**Our Rest API** has many endpoints which **require authentication**. Those endpoints provide data like user workspaces, projects, virtual users and more. To access user-protected endpoints, one must:

- **Login** to get an authentication token (like we did previsouly),
- **Send the auth token** within an `Authorization: Bearer TOKEN` http request header, for each subsequent request.

That's exactly what we're going to do here.

### Retrieving User Workspaces

We're now particularly interested in **querying the workspaces of our user**. This is part of the *Workspaces* API Endpoints.

![Workspaces API](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/workspaces-api.png "Workspaces Rest API Endpoint from Swagger API Docs")

We're going to perform a `GET` request to the endpoint with path `/workspaces/member-of`. It should return a **Json** response containing the user workspaces. Here is an example response:

```json
[
  {
    "created": "2018-04-23T12:40:00.133Z",
    "description": "This is my personal workspace.",
    "id": "workspaceId",
    "lastModified": "2018-04-23T12:40:00.133Z",
    "name": "Personal",
    "userId": "myUserId"
  }
]
```

Let's create an HTTP request within JMeter to query those. That's pretty simple like shown on the screenshot below.

![Workspaces API](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/workspaces-member-of-endpoint.png "Call member-of endpoint from JMeter")

Here we have setup an HTTP request to query the workspaces of the user:

- **Http Method**: must be a *GET* request, no parameters involved,
- **Http Scheme**: `https` since our Rest API is [secured by SSL](https://www.digicert.com/ssl/),
- **Hostname**: `api.octoperf.com`,
- **Path**: `/workspaces/member-of`.

Is it finished? Not yet. For now, if we don't provide the authentication token, the server will reject our request.

![Workspaces Members of](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/workspaces-member-of-endpoint-failure.png "Server returns an error")

The server rejects the request with an [Http 4xx error](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors): `401 Unauthorized`.

> Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.

We need to provide the authentication token by including an `Authorization` header within the request. How? By adding an [HTTP Header manager](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Header_Manager) to the request.

### Adding Authorization Header

![Workspaces Members of](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-http-header-manager.png "Setting extracted token within Authorization header")

Remember: we have previously extracted the `token` from the `/public/users/login` endpoint server response. Now, it's time to reuse it to retrieve **access protected** resources:

1. First, add an *Http Header Manager* under the *getWorkspaces* HTTP Request,
2. Add the `Authorization` header, with value `Bearer ${token}`.

![View Results Tree](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/get-workspaces-result.png "Got the workspaces from the server")

Nice! It's working now! We've got all the workspaces which belong to the logged user.

![View Results Tree](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/get-workspaces-result-2.png "Authorization header has been sent within the request")

The authorization header has been successfully included within the request headers. But, one thing that's pretty annoying is: **The Json is not formatted correctly**. Why?

> Most servers send json in compact format, skipping indentation. This is done for performance reason (reduces bandwidth usage and server CPU usage)

### Format Json Response

To overcome this issue, the [JSON Formatter PostProcessor](https://jmeter-plugins.org/wiki/JSONFormatter/) does the job very well.

![JMeter Json Formatter PostProcessor](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-formatter.png "JMeter Json Formatter Post-Processor")

See our [JMeter Plugins Installation Guide](https://blog.octoperf.com/jmeter-plugins-installation-guide/) to learn how to install the **Json Plugins**. Another option is to format the Json yourself using a [JSR223 Script](https://blog.octoperf.com/reusable-sample-jmeter-scripts/).

![JMeter Json Response Formatted](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-response-formatted.png "Json is pretty printed now!")

Now, we can leverage the power of the [Json Assertion](https://blog.octoperf.com/jmeter-assertions-the-ultimate-guide/#json-assertion) (introduced in **JMeter 4.0**) to check the server response.

## Using Json Assertion

We're going to make sure the server response contains the `Personal` workspace. That's a job for the **Json assertion**. To add a Json assertion, right-click on the HTTP Request sampler, then select `Add > Post Processor > Json Assertion`.

### Configuration

![JMeter Json Response Assertion](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-assertion.png "Asserting the response contains a Personal workspace")

The Json assertion is configured as following:

- **Assert Json Path Exists**: `$.[1]['name']` refers to the second workspace returned, and takes its `name`,
- **Additionally Assert Value**: Check to enable checking the value of the `name` field,
- **Expected Value**: should be `Personal`.

### Execution

Suppose we assert the *expected value* is `Other` instead of `Personal`.

![JMeter Json Response Assertion Failure](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-assertion-failure.png "The Json Assertion Fails when looking for workspace named 'Other'")

As expected, the assertion fails with the following message:

```
Assertion error: false
Assertion failure: true
Assertion failure message: Value expected to be 'Other', but found 'Personal'
```

### Performance

Of course, you're not constrained to use only Json Assertion. you can also use The [JMeter Response Assertion](https://blog.octoperf.com/jmeter-response-assertion/) if you want to. It's even **beneficial in terms of performance**, because the *Response Assertion* consumes less CPU / memory resources than the Json assertion according to our [Assertions Performance Comparison Table](https://blog.octoperf.com/jmeter-assertions-the-ultimate-guide/#performance).

## Simulating Dynamic Behavior

Now that we know how to login on a Json Rest API and send requests to **access protected** endpoints, let's see how we can simulate a `dynamically behaving` user with JMeter. 

That's the final part of this tutorial:

- First, we're going to **extract a random workspace ID**, (will be `${workspaceId}`)
- Second, we're going to query the projects of that workspace using the endpoint `/projects/by-workspace/${workspaceId}/DESIGN`.

![Projects Rest API](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/octoperf-projects-rest-api.png "OctoPerf's Projects Rest API Endpoints")

The last Rest API endpoint interests us. We're going to call it from JMeter, but first we need to **extract a random workspaceId**.

### Extracting WorkspaceId

![JMeter Random Json Extractor](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-json-extractor-workspace-id.png "Extracting random workspaceId")

The extractor is configured as a post-processor of the `getWorkspaces` request with the settings:

- **Name of created variables**: `workspaceId`,
- **Json Path Expressions**: `$..id`,
- **Match No**: `0`, which is random.

This extracts a random workspaceId, and puts it in the `${workspaceId}` variable.

### Querying Projects

Finally, we need to query the projects according to the previously extracted `workspaceId`. For this purpose, I have **duplicated and modified the previous request** to gain some time.

![JMeter Random Json Extractor](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-get-projects.png "Querying projects with workspaceId variable")

Here we have setup an HTTP request to query the projects of a workspace:

- **Http Method**: must be a *GET* request, no parameters involved,
- **Http Scheme**: `https` since our Rest API is [secured by SSL](https://www.digicert.com/ssl/),
- **Hostname**: `api.octoperf.com`,
- **Path**: `/design/projects/by-workspace/${workspaceId}/DESIGN`. `DESIGN` states for projects enclosed within a workspace. (and not within a result, which would be `RESULT`)

I guess we're ready to run a quick iteration to try this out!

### Viewing Results

![JMeter Random Json Extractor](https://blog.octoperf.com/img/blog/jmeter-rest-api-testing/jmeter-get-projects-result.png "Execution results in querying the projects")

If we execute the user multiple times, we see that the **response varies** depending on the **random workspaceId** being extracted.

## Final Words

**JMeter** is really well suited for Rest API Testing, especially those based on the [Json Format](https://en.wikipedia.org/wiki/JSON). **Testing Json APIs with JMeter is really easy**. 

Basically, if you master the *JMeter components* mentioned above, you're good to go!

If you want to dig further, I strongly suggest you to read our articles about:

- [JMeter JsonPath Extractor](https://blog.octoperf.com/how-to-extract-data-from-json-response-using-jmeter/): extract any content from a Json response, learn more about the **JsonPath syntax**,
- [JMeter Json Assertion](https://blog.octoperf.com/jmeter-assertions-the-ultimate-guide/#json-assertion): specifically assert json responses,
- And [JMeter Plugins](https://blog.octoperf.com/jmeter-plugins-installation-guide/) like the **Json Formatter** may make your life a lot easier by **formatting the output**.

Feel free to share this guide if you found it useful!
