Testing Microservices With JMeter
Testing Microservices With JMeter
As microservices gain popularity, it's important to learn about testing. Learn all about testing microservices using JMeter in this thorough tutorial.
Join the DZone community and get the full member experience.Join For Free
Learn why microservices are breaking traditional APM tools that were built for monoliths.
The advantages of microservices have resulted in more users and growing popularity, but at the same time the challenges of developing and testing Microservices surface. In this post, we will demonstrate one of the possible scenarios of testing Microservices with Apache JMeter™. A load testing scenario for microservices should test the interactions between these services.
Let's imagine we have a group of services. The first one is responsible for user authentication, the second one acts as a bookshelf service helping to find information about books, and the last one allows ordering books. These are microservices because they are small, loosely coupled, scalable and each solves its own problem.
We will create a simple JMeter test project for the set of microservices mentioned above that will test the group of services in the same thread. For simplicity's sake, all the information about books is hardcoded so no DB of any sort will be used.
Since we are going to use Groovy in this article, a very basic knowledge of it would be nice to have. Don't feel upset if you are not familiar with Groovy. We are not going to do anything complicated here anyway and the scripts used below are very easy to read.
The services that are used in the current tutorial can be found on the GitHub repository called Library (I didn't try to be creative here).
To run these services we need .Net Core SDK 2.1 or higher. Please download and install it from the .Net Core official website if you don't have it already.
The Library project contains three services. After cloning the project locally, open the project folders in a command line tool and run dotnet run to start the corresponding service. Those who are interested in more information about the dotnet cli tool can find more details here.
The dotnet run result should be something similar to this:
Run the same command for all 3 services and we are ready to go!
Since the mentioned services are HTTP based RESTful services, we need the HTTP Request Sampler to perform the service call.
1. First, add a Thread Group.
2. Now, add an HTTP Request sampler to the newly created Thread Group.
Since the book search and order services are protected by JWT, we need to request a valid security token from the Library.Authentication service. More details about what a JSON Web Token is can be found on https://jwt.io/.
3. Configure the HTTP Request Sampler to send a request to the Library.Authentication service.
The service does not do sophisticated user checks, but due to the validation model of the service, it requires valid login credentials. So, add a parameter to the Authentication request and provide any JSON with a valid email and non-empty Password fields.
Here we have an additional thing to do. The service I use in this article accepts/sends data as a JSON, so we have to indicate it in the request header.
4. Add an HTTP Header Manager before the HTTP Request Sampler we added earlier and add a header Content-Type: application/json as in the screenshot below. That will add a corresponding header to all the requests we send to our services.
5. To verify that we get a JWT token back, add a temporary View Results Tree listener.
6. If everything was done correctly we should get a response similar to what we have below:
7. If this is what you got as a response, you can remove the temporary View Results Tree component and proceed further.
If you are interested in more details about JSON Web Tokens and Bearer Authentication I would recommend starting from here.
Now we have a JWT token for requesting secured resources from our Library. We need to add it to all the upcoming request headers so that the protected services will verify our identity. To do this, we need to parse the token from the previous request's response. There are a few ways to parse a JSON in JMeter but the simplest one is to use the JSON Extractor. It is described in great detail here, so I won't go into details about how it works.
8. Add a JSON Extractor to the Authentication Request.
9. Configure it as in the screenshot below.
It will do two things. First it will extract the JSON value with the key "jwt" from the response and second it will +add it to JMeter variables with the name jwt. Later, this value can be accessed through one of predefined runtime variables with the name vars. It's as simple as that.
More information about other predefined variables can be found in the JMeter documentation.
Now that we have the JWT token extracted and stored in vars, let's use it to call the library service.
10. Add a second HTTP Request Sampler to our test thread. Its configuration is similar to the previous one (besides the path and the port of course).
Here is the important part. To access protected resources, we have to add the previously extracted JWT token to this request header before sending it.
JMeter supports a few ways to modify a request and deal with dynamic data. Here I will use the JSR223 PreProcessor and with the Groovy scripting language. Groovy is a widely known Java-based scripting language and the JSR223 PreProcessor allows writing scripts which that be executed before a request is being sent.
Details about JMeter preprocessors can be found in the following article and references to Groovy can be found on the official website and in this article. Also, there is this great article comparing available scripting options in JMeter.
11. Add a JSR223 PreProcessor with the following script:
These are enough to extract "jwt" from vars and add it to the request header.
12. To check if we are able to reach the protected resource I suggest to add a Result Listener and check if you see the result from the books service. If everything is ok you should see something similar to the screenshot below.
Now the final step. Since we have a response from the books service we can extract the book information and use it to call the ordering service.
13. Add a second JSON Extractor to the Books Request to parse a book id. The steps necessary for that are the same as for the "JWT JSON Extractor." The only difference is that here we need to parse an array.
14. Please pay attention to the JSON Path expressions field in the screenshot above. "$.id" means that we take the ID of the first book of the response. We store it in the "vars" with a key "bookId" so that it can be used later.
15. Now the final step. We need to create the last HTTP Request Sampler to call the ordering service and provide the bookid that we have extracted from the previous call.
The ordering service expects a book id as a part of the route, so we need to modify the request URL before sending it.
The plan is to use JSR223 PreProcessor to extract the bookId and add it to the end of the URL so that the ordering service can parse the book id.
16. Add a new JSR223 PreProcessor to the "Order a Book Request" sampler and add the following script to the Script section of it.
The result is expected to be similar to this screenshot.
Here we extract the bookId and store it in the corresponding variable, then we append the bookId value to the outgoing request URL.
For the URL modification (to add the book id to the end of the URL) we will use the predefined variable ctx, which encapsulates virtually all of JMeter's functionalities and provides runtime access to everything that is involved in a test. Details about what ctx is and how it can be used can be found in the official documentation as well as articles like Using Beanshell for Beginners and How to Use BeanShell: JMeter's Favorite Built-in Component. CTX can be used in Groovy, Java, BeanShell and more.
After this step, we should be able to perform a successful request to the ordering service. To check if the call is actually successful or not, let's add a View Results Tree and assertion components to the "Order a Book Request" step.
Please perform the following two steps.
17. First, add a View Results Tree component to check the response from the ordering service.
18. Second, add a Response assertion component as in the screenshot below to verify the response status code from the ordering service.
19. Check the Response Code and the Equals radio buttons in the response assertion component to verify a response code against the given pattern. Since we expect the request to be successful, the pattern to check against will be "200" (HTTP Code OK). The final look of the Response Assertion component should be similar to this screenshot.
After all these steps we should have a test that
- Sends a request to the authentication service and gets a JWT token.
- Extracts the token and adds it to the upcoming request headers.
- Sends a request to the books service and gets the books list.
- Parses the books list and stores the first book id in the vars variable.
- Modifies a URL of the ordering service before a call and sends the request to order a book.
All these steps now should work as a single test. If everything went smoothly you should see the similar picture.
All that is left to do is to remove the View Results component in the "Books Request" step as we added it for a diagnostic purpose and don't actually need it anymore.
For building and running the test and services used in this article following tools were used:
To learn more advanced JMeter, go to our free JMeter academy.
If you're testing microservices and need to share your results with team members or make scalability easier, you might want to consider running your test in BlazeMeter."
After creating your JMX file, upload it to BlazeMeter and run your tests. With BlazeMeter, you will be able to collaborate on your tests and reports with team members and managers, scale to more users from more geo-locations, and get advanced reports.
This blog post demonstrated a testing scenario of a group of independent, loosely coupled services, which were tested together to verify the interactions between them. This test has verified only the happy-path scenario. In your test, you will probably have more requirements to verify, like a "book not found" scenario, but I think you got the point.
For more microservices testing techniques, I recommend reading "Testing Strategies in a Microservice Architecture."
To try out BlazeMeter, request a demo, or put your URL in the box below and your test will start in minutes.
Published at DZone with permission of Artyom Avetisyan , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.