JMeter – How To Test REST API / MicroServices

Overview:

There are so many ways and tools available to test a REST API.
When I had a requirement to test a REST API, after looking at various tools & options, I settled on JMeter for the following reasons.

  • JMeter is FREE & Open Source.
  • JMeter can read your testdata from the CSV file out of the box. Parameterization is very easy.
    • API can be tested with multiple sets of data easily.
  • JMeter has a powerful ‘Response Extractor‘ s  – which can be used to extract information from the API response (JSON / XML / Regular expression) and use it in the subsequent requests in the test.
  • JMeter has tons of ‘Assertions‘ – to verify the if the API response is as expected.
  • The JMeter test we created for functional testing can also be used for performance testing.
  • ANT / Maven / Gradle plug-ins to execute the test as part of your build.
  • Easy integration with Jenkins to run the test periodically & Jenkins has a plugin for JMeter to parse the result file & display nice charts.

Installing JMeter:

If you do not have JMeter installed in your machine, check this link. It has detailed steps to install JMeter.

Once you launch JMeter, You will see Test Plan element which is the root node of the JMeter test under which we will add various JMeter elements for our test.

Create a Simple API JMeter Test:

Now Lets add the required elements for our test.

  • Add a Thread Group under the test plan. (Rightclick on Test Plan –> Add –> Threads (users) –> Thread Group)
    • We update the number of users, number of iterations etc in the Thread Group.
    • Let them be 1 for now.
  • Add a HTTP Request Sampler under the Thread Group.  (Rightclick on Thread Group –> Add –> Sampler –>HTTP Request)
    • Sampler is a type of JMeter request.
    • REST is an approach & it uses HTTP protocol. So we add the HTTP Request sampler.
    • Update Server IP / Hostname as myapiservername.com [For this API url : http://myapiservername.com/rest/api/path]
    • Update the API path /rest/api/path

JMeter2

  • Send Files with the Request   – should have the path of your request JSON file OR include the request JSON in the Body Data section of the HTTP Request.
  • Add a HTTP Header Manager   (Rightclick on Test Plan –> Add –> Config element –> HTTP Header Manager)
    • In HTTP Header Manner config page, click on ‘Add’.
    • Include this name-value pair.
      • Name=Content-Type
      • Value=application/json
    • If your API expects APIGEE key, then include it here or ignore.
      • Name=apigeekey
      • Value=test@123

JMeter3

  • Add a HTTP Authorization Manager  – Required in case of any authentication. (Rightclick on Test Plan –> Add –> Config element –> HTTP Authorization Manager)
    • Update the Base URL as http://myapiservername.com
    • Update the username
    • Update the password
  • Under Test Plan, add a listener – View Results Tree

Your JMeter test will look like this (I did not include the listener).

JMeter1

 

Now if you run this, you should be able to send the request and get the response successfully.

Note: If it does not work for some reason, try changing the HTTP Request Implementation to Java/Other values and give a try.

rest001

Whatever we have done so far is a very simple test – like a POC. Now lets see how it can be improved further.

Parameterizing the test data:

In the above example, we send the hard coded request JSON to test the API. We might have to test the API for different sets of data.

Lets take a very simple example, I have an API which gives the book name and price details for the book id request i send.

Testdata in CSV:

csv1

Request JSON:

Lets assume that our API request in the below format.

{
    "bookid": 1
}

Response JSON:

Lets assume our API response is as given below.

{
    "bookname": "Awesome Jmeter"
    "bookprice": 23.5
}

JMeter4

 

Add CSV Data Set Config under Test Plan & update the details as given above.

  • Variable Names : can be blank. JMeter will take the CSV column names as variable names.
  • Recycle on EOF? : should be FALSE. We are going to test each row only once.
  • Stop Thread on EOF? : should be TRUE. It will stop the JMeter test automatically once we tested for all the rows.
  • In Thread Group, select the ‘For Ever’ check box in the Loop Count.

Parameterize:

Instead of sending the hard coded book id, lets parameterize it by using the value from the ‘id’ column of the CSV file.

JMeter5

 

That’s it. If you run the test now, it should send 6 requests one by one for each row in the CSV file.

We can do a lot better than this – what if there are different types of request – GET / POST / DELETE / PUT / PATCH etc. It is super easy with JMeter. I drive my tests completely through a spreadsheet as shown here. Please check here for the advanced usage of JMeter – REST API – Data-Driven testing

rest003

 

Assertion:

If we can send the request and get the response, are we done? Nope!! But, We are almost there!!

We need to validate if we get the expected response. So, one last step would be to add the assertion.

I have the expected book name and price details in the CSV file shown in the above example.  Lets use those details to check if our API works as expected.

Add Response Assertion under HTTP Request as given below. We need to verify if we have the expected book name and price in the response. Add them as given below.

JMeter6

 

This assertion will validate the response and Pass/Fail the test accordingly.  (Ensure that Pattern Matching Rules is ‘Contains’ as we are checking only for the book name and price. We are not verifying the whole response.)

Duration Assertion:

JMeter not only verifies text – but also the ‘time‘ the request took. If we add ‘Duration Assertion’ and set an acceptable time limit, JMeter can confirm if the response was received within the time limit.

microservice-rest-result

Extracting Data From JSON Response:

Sometimes you might want to extract specific data from JSON response and pass this data to the subsequent request in JMeter. JMeter provides a JSON Extractor to extract particular value from the JSON response.

Lets assume, my sample response looks like this.

{
   "title":"In Search of Lost Time",
   "author":"Marcel Proust",
   "id":1
}

I could add a JSON Extractor as shown below to extract the value of the author into the variable authorValue.

rest002

  • $ refers to the root element in the JSON Path expressions
  • ‘author’ is immediate child of the root element. So it can be accessed using $.author
  • Match Number gives the Nth match. If you want all the matching value in an array, Match Numbers should be -1
  • Default Values – used when there is no match

Lets consider below JSON response

{
   "store":{
      "book":[
         {
            "category":"reference",
            "author":"Nigel Rees",
            "title":"Sayings of the Century",
            "price":8.95
         },
         {
            "category":"fiction",
            "author":"Evelyn Waugh",
            "title":"Sword of Honour",
            "price":12.99
         }
      ],
      "bicycle":{
         "color":"red",
         "price":19.95
      }
   }
}
  • To get the first book price – $.store.book[1].price
  • To get all prices from category – $..price

More information on this can be found here.

Performance Testing on REST API:

You might have verified the API functionality!

But, How do we know that about the following information on the API?

  • Response time it takes
  • Concurrent users it can support
  • User load at which it breaks
  • CPU/Memory usage
  • Memory leak

JMeter can help here as well by using the same test we had just created!!

  • Update the Number of thread in the Thread Group.  If you enter 10 as number of users & run,  JMeter will simulate 10 concurrent users.
  • Update the Ramp up period (in seconds). For ex: If you have 10 users & 50 seconds as Ramp up period, JMeter will start creating 1 virtual user for every 5 seconds.
  • Loop count: Select ‘Forever’.
  • Under Scheduler, enter Duration in seconds. [Entering 600 will run the performance test for 10 mins with 10 Virtual Users.]
  • Update CSV Data Set Config : ‘Recycle on EOF?’ – set it to TRUE – [FALSE will read the CSV data only once. We need enough data for VUsers to run for 10 mins. So setting it to TRUE will feed the same set of test data once it is read]
  • Add a ‘Aggregate Report’ listener under the Test Plan.

Run your Meter test now. ‘Aggregate Report’ will give a basic idea of your REST API performance metrics like number of requests made in given duration, average response time, throughput, ‘90% line’ etc. [Note: It is not a good practice to run JMeter performance test in GUI mode as we just did now as it consumes more memory. Please check this Tips & Tricks for the best practices to be followed.]

 

Summary:

We just have created a Simple Data Driven Framework to test the functional behavior of REST API using JMeter without using any programming language.  We also saw how to do performance testing on our API using JMeter by reusing the same script created for functional testing.

You might want to continue reading more about for the advanced usage of JMeter – REST API – Data-Driven testing

Are you new to JMeter? – Then you should totally check this article out which gives more information on the JMeter best practices and common mistakes beginners make.

Happy Testing & Subscribe  🙂

 

Share This:

38 thoughts on “JMeter – How To Test REST API / MicroServices

  1. I followed the method to test my rest API service but I am getting a 415 error code unsupported media type error message.
    I am using VPN to connect to the application. It is a POST method

    1. Hi Anand,
      Server will return 415 error code when it is not able to process the content-type of the request. So I assume you have set it to application/json.
      Does your request body have any json?

      1. Yes my request has Json. Also I have set the Content Type to application/json. But I get the issue still

  2. Hi,
    I may not be able to provide the actual request but will provide the details of my request
    HTTP Request Sampler:
    Host name: ; Port: 8080
    Implementation Java; Protocol: HTTP; Method POST; Content encoding; UTF-8
    Path: /rest/user/register// user id is any random number and access token is passed as NULL so that the system identifies it as a System Admin user registering to the service
    Follow redirects: Checked; Use Redirects: Checked
    Raw POST Body : {“name”:”adminNew”,”userCategory”:”SYSTEM_ADMIN”,”companyCode”:”DEFAULT_COMPANY_CODE”}
    Http Header Manager
    Content-Type: application/json

    I was just wondering whether this could be something related to Json lite not recognized by the server. Kindly put in your thoughts for the same.

  3. Also tried with Advanced Rest Client Application with Chrome, but here as well I am getting error code 415.

    But the request is working fine with Postman client

  4. I am resending the requests in my previous comment which has not appeared
    Path: /rest/user/register/userid/accesstoken where user id is any random number and access token is passed as NULL so that the system identifies it as a System Admin user registering to the service

    1. As you confirmed that you 415 error even with Chrome extn, the issue does not seem to be specific to JMeter.

      Your setup looks good to me. Lets try these!

    2. Add ‘Accept = application/json’ in the header manager.
    3. You seem to have set UTF-8 already. Try removing this.
    4. If it is still does not help, Can you see how the request is being sent by the Postman client – using JMeter proxy server? If we can record, then we will know what is missing in the request we send through JMeter.

  5. Hi,
    My script started to work as the dev team confirmed that they are serializing the json to string at client side and desterilize it at server. So i gave text/plain as content-tpe and it started working. Thank you for all the help in understanding things.
    I have a new problem, I am using Response Assertion to validate my response against csv. But I would also like to enter the status of each request in the csv against each row. Will I be able to use Bean Shell assertion here if so how? Kindly explain

    Thanks
    Anand

    1. Response Assertion can also compare the response code.
      But, We will have more control over Beanshell Assertion.

      To check the HTTP response code (assuming you have stored the expected response code in CSV in ‘resCode’ column),

      if (ResponseCode.equals(vars.get("resCode")) == true && ResponseData.contains(vars.get("expectedMessage")) == true ) {
      SampleResult.setResponseOK();
      }else{
      Failure=true;
      FailureMessage="Response code/data not as expected";
      }

  6. Thank you for the response, this works. I tried adding a BeanShell listner to the plan which actually writes the error code from the response. But the write file loops infinitly, i.e the values are entered endlessly in the csv. Below is my code

    refnum = vars.get(“Error Count”);
    f = new FileOutputStream(“D:/Apache Jmeter 2.11/apache-jmeter-2.11/Input_Admin.csv”, true);
    p = new PrintStream(f);
    this.interpreter.setOut(p);
    print(“Error Count,” + refnum);
    f.close();

    Could you please help

  7. also would like to know if I need to write the results into a particular cell say Column D Row 1 to 9 from jmeter will that be possible??

  8. When we use the CSV file for Post Request than we need to change the content-type from application/json to text/csv ? if yes then if you services only allow json request then you can advise the solution?

  9. I using protocol https with 3 headers to test API. My test succeed in post man but i have response code 401 ( unauthorized ) when setting up and running in jmeter. I’m using same value for header parameter in postman and jmeter.
    Please help me! Thanks so much!

  10. Hi,

    I was trying to make a script to test REST services using Jmeter.
    Till now I was using Chrome’s Advanced REST Client.
    My authentication request was GET and it was something like this in Advanced REST:
    https://username:password@URL:portnumber
    its a GET request

    Now when I am using Jmeter. I tried following ways:
    I added HTTP Authorization Manager and mentioned Base URL and Username/password inside it.
    When I am trying to do a request then its showing me “Unauthorized”

    I also tried to login using normal https request but no success.

    When accessed manually, a authorization popup window appears and username and password is submitted inside this window.

    Please suggest me a way for how to login using Jmeter.

  11. Thank you . This article gives me a clear idea. But let me know how can I find out
    a. CPU usage
    b. Memory Leak.

  12. Thanks for the post, Could you please write an article on how to compare two xml responses and print the output which are not identical – this is for functional tests. Thankyou beforehand for help.

  13. I am having problem like – my rest api will give result if we give access token or else it give 401 error. How to pass where to pass access token in jmeter.

  14. Query: I want to extract large data from Response Data of Request#1 and apply to BodyData of Request#2 as well as need to parameterize few values. Is it possible from Jmeter GUI? If Yes, please help.

  15. How to perform performance testing of REST api if we use PDF or Text files as input for Post Request?

  16. Can you write a post or a video to functional test REST API calls GET, POST, PUT, PATCH, DELETE and validate responses in Jmeter.

    Not load test…

    Pass data for POST, PUT, PATCH via excel and validate the responses in detail. like data driven

    I want to perform functional rest API testing on Jmeter and then load test those api’s just by increasing users.

    Will be a extremely helpful to others as well

    1. I thought most of the information was already here. Yes, I could add more information on the data-driven testing part.

Leave a Reply to vIns Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.