Microservices Testing using vREST NG
Dheeraj Kumar Aggarwal
Helping businesses solve API and Traceability problems | Product Evangelist | Atlassian Expert | API Automation Expert | Creator of vREST NG
Microservices architecture is now a widely adopted practice to handle large systems as compared to monolith architecture. With microservices, you can break your larger system into multiple subsystems and each sub-system can be developed, deployed, and scaled independently. Validating APIs for micro-services architecture has become more complex because we have to validate each microservice as well as their integration.
We can handle the complexity using the following approach:
- Validate each microservice in isolation. And all the other microservices on which this microservice depends, we should replace them with test doubles.
- We need to verify the structure of requests which we are sending to other microservices.
- We also need to verify the response structure of our test doubles against our real microservice response.
In this post, we are going to handle only the first part and a little bit about the second part. We are going to answer the following questions:
- How we can set up test doubles for our microservice? So that we can validate our microservice in isolation?
- How we can validate the actual request sent to our mock service?
- How we can tear down our test doubles once we have validated our microservice?
For setting up test doubles, I am going to use an on-demand test double service Mountebank which is an open-source tool to provide cross-platform, multi-protocol test doubles over the wire. You may use any mock service of your choice.
Pre-requisite knowledge
- Basic understanding of vREST NG Application
- Basic understanding of Mountebank Service
Let's get started.
Sample Microservice Application:
For this, I am going to use a sample project on microservice written by "Mike Mackrory". The repository link is as below:
https://github.com/echovue/zipcode-microservice-node
This is a sample NodeJS Based microservice implementation that determines the distance between the specified zip codes.
This microservice depends on an external service "https://www.zipcodeapi.com/" for its distance calculation.
An example request to our microservice will look like this:
https://localhost:3000/distance/97035/97001
Assuming our microservice is running on port 3000. Here 97035 is one zip code and 97001 is another zip code.
And the response should be:
{ "distance": 107.319 }
In this article, we are going to validate the above sample microservice. For validating this microservice, we will create an on-demand test double for our external service "https://www.zipcodeapi.com/rest" using Mountebank.
Setting up our test application
1. Clone the repository on your local system and install the dependencies using the following commands:
$ git clone [email protected]:dheerajaggarwal/zipcode-microservice-node.git $ npm install
2. Now execute the following command to run our local server
$ ZIPCODE_API_BASE_URL="https://localhost:4545/rest/" PORT=3000 npm start
The above command will start our server on PORT 3000 and we will be creating our test doubles on PORT 4545.
Now our test application is running. Let's proceed further.
Download and start MounteBank Server
Now we will need to set up our on-demand test double server. The installation is quite simple and can be done using the following command:
$ npm install -g mountebank
And to run the mountebank server, simply execute the following command:
$ mb
That's it. Our Mountebank server will automatically run on PORT 2525. You may read more information on this by going to the Mountebank website.
Download and install vREST NG Application
You may download the vREST NG application from our website (https://ng.vrest.io) and install it. Once installed, use the Pro version to proceed further as this tutorial will use the functionality of local hooks which is only supported in the Pro version.
Brief Introduction to Local Hooks
vREST NG provides Hooks functionality through which you may integrate any external application/tool easily with vREST NG. It provides two types of hooks:
- Local Hooks: Local Hooks are executed only for test cases in which they are linked. vREST NG provides two types of test case local hooks, pre and post. Pre local hooks are executed before the execution of the test case. And Post local hooks are executed after the test case execution but before the test case validation. A test case will only pass when all of its assertions are passed and all of its linked local hooks are passed as well.
- Non Local Hooks: Other types of hooks are non-local hooks which are not specific to any test case. These types of hooks are majorly used for integrating external tools like Jira, Slack, Hipchat, TestRail, etc. but out of scope for this article.
Configure the On-Demand Test Double in MounteBank
For configuring the on-demand test double, we will create the following hooks:
- Pre Test Case Local Hook to setup the on-demand test double for our external service.
- Post Test Case Local Hook for verifying the request content fired by our test application to the external service.
- Post Test Case Local Hook to delete our on-demand test double.
Let's look at the above steps in detail:
1. Setup the on-demand Test Double
For this, we will create a hook "Pre Test Case Local Hook" in vREST NG Application with the following details. This will create a test double in our on-demand mock service and this test double will be used by our microservice which we are going to test.
Method: POST URL: https://localhost:2525/imposters Request Body: { "port": 4545, "protocol": "http", "recordRequests": true, "stubs": [ { "responses": [ { "is": { "statusCode": 200, "body": "{\"distance\": 107.319}", "headers": { "Content-Type": "application/json" } } } ], "predicates": [ { "and": [ { "equals": { "path": "/rest/O9QwwS6jLrvMj25AYBO3XNYfUI3HcDc2ubwEn724UFqFc9AiQkasolw4rtRUBC4B/distance.json/97035/97001/mile", "method": "GET" } } ] } ] } ] }
This is how we instruct Mountebank to return a specified response on certain conditions (predicates). Make sure, that `recordRequests` option is true. Only then we will be able to verify the requests received by Mountebank. Let's take a step by step, how we can create this hook in vREST NG Application:
1. First, create a Pre Test Case Local Hook in the Hooks tab of the vREST NG Application as shown in the image below:
2. Now, once the hook is created, then set the Request Body like this:
That's it, our Pre Test Case Local Hook is now ready.
2. Verify the request fired to our test double service
In this step, we will verify the request fired by our test application to external service (mocked). Mountebank provides an endpoint to check the requests received by it. For this, we will create a hook "Post Test Case Local Hook" in vREST NG Application with the following details.
Method: GET URL: https://localhost:2525/imposters/4545 Expected Body: { "protocol": "http", "port": 4545, "numberOfRequests": 1, "requests": [ { "requestFrom": "{{*}}", "method": "GET", "path": "/rest/O9QwwS6jLrvMj25AYBO3XNYfUI3HcDc2ubwEn724UFqFc9AiQkasolw4rtRUBC4B/distance.json/97035/97001/mile", "query": {}, "headers": { "host": "localhost:4545", "Connection": "close" }, "body": "", "{{*}}": "{{*}}", "timestamp": "{{*}}" } ], "{{*}}": "{{*}}" }
The above hook will ask Mountebank for any incoming requests it has received. Let's take a step by step, how we can create this hook in vREST NG Application:
1. Create a Post Test Case Local Hook in the Hooks tab of the vREST NG Application as shown in the image below:
2. Now, once the hook is created, then set the Expected Body like this:
That's it. This hooks will validate the request received by Mountebank.
3. Delete our on-demand test double
Now we will look at, how we can delete our test doubles which we have set up with Pre Test Case Local Hook. For deletion, we will create a new Post Test Case Local Hook which will invoke an API on Mountebank to delete the desired imposter:
Method: DELETE URL: https://localhost:2525/imposters/4545
Now, let's create this hook step by step:
1. Create a Post Test Case Local Hook for deleting the imposter like this:
2. Click on the Confirm button to create the hook, that's it.
Till now, we have configured all the hooks to setup, verify, and teardown the imposters on Mountebank. Now let's configure a test for our microservice.
Configuring the test for our microservice:
For configuring the test, simply create a test case in vREST NG with the following details:
Method: GET URL: https://localhost:3000/distance/97035/97001 Expected Body: { "distance": 107.319 } Expected Schema: { "type": "object", "properties": { "distance": { "type": "number" } }, "required": [ "distance" ] }
Let's do it step by step.
1. First Create a test case in the Test Cases tab of the vREST NG Application. Just click on `Plus` button available in the left-most pane to create the test case. And provide the following details as shown in the figure below:
2. Link the local hooks which we have created earlier. See the Local Hooks field in the figure below:
3. Now, provide the Expected Body as shown in the figure below to validate the response content.
4. Now provide the Expected Schema as shown in the figure below to validate the response structure.
That's it. Now let's try to execute our test case. As we can see in the following figure that our test case has passed.
Just check the rightmost pane in the above image, you may see that all the assertions, as well as our local hooks, are also passed.
To see the hook results in detail, you may click on the Hooks tab in the rightmost pane as shown in the figure below.
Now, just click on the desired hook to see the hook specific details as shown in the figure below:
This is how you may validate your microservices in vREST NG. Do try out vREST NG to validate your microservices and let us know your feedback, pain points, share your experiences with us. You may download vREST NG from our website (https://ng.vrest.io).