Developer blog

Postman Tips for Better API Testing

Postman Tips for Better API Testing

April 29, 2025 By Esau Silva

Postman is a powerful tool for testing and working with APIs. In this blog post, I will describe some Postman tips for better API testing that I have used for quite some time and have helped tremendously. Testing an API Response Postman makes it easy to test API responses. You can test for HTTP Status Codes, expected and non-expected responses, and headers, among other useful information about the response. For the rest of this post, I will be calling the GitHub API for the examples. Say we want to test a successful response by calling the following endpoint: https://api.github.com/users/esausilva   The following will be the response. { “login”: “esausilva”, “id”: 9492978, “node_id”: “MDQ6VXNlcjk0OTI5Nzg=”, “avatar_url”: “https://avatars.githubusercontent.com/u/9492978?v=4”, “gravatar_id”: “”, “url”: “https://api.github.com/users/esausilva”, “html_url”: “https://github.com/esausilva”, “followers_url”: “https://api.github.com/users/esausilva/followers”, “following_url”: “https://api.github.com/users/esausilva/following{/other_user}”, “gists_url”: “https://api.github.com/users/esausilva/gists{/gist_id}”, “starred_url”: “https://api.github.com/users/esausilva/starred{/owner}{/repo}”, “subscriptions_url”: “https://api.github.com/users/esausilva/subscriptions”, “organizations_url”: “https://api.github.com/users/esausilva/orgs”, “repos_url”: “https://api.github.com/users/esausilva/repos”, “events_url”: “https://api.github.com/users/esausilva/events{/privacy}”, “received_events_url”: “https://api.github.com/users/esausilva/received_events”, “type”: “User”, “user_view_type”: “public”, “site_admin”: false, “name”: “Esau Silva”, “company”: “Ingo Payments”, “blog”: “https://esausilva.dev/”, “location”: “Nashville Metro Area, TN”, “email”: null, “hireable”: true, “bio”: “Full Stack Software Engineer”, “twitter_username”: “_esausilva”, “public_repos”: 27, “public_gists”: 6, “followers”: 166, “following”: 19, “created_at”: “2014-11-01T02:42:50Z”, “updated_at”: “2025-04-04T01:32:39Z” } We want to test for 200 OK status code, that id is an integer, company is not null and name is equal to “Esau Silva”. We would write the following JavaScript code under the “Scripts -> Post-response” tab of the request. // Get the request response var res = pm.response var resData = pm.response.json() // Test assetions pm.test(“Assert HTTP Status = 200 OK”, function () { res.to.have.status(200) }); pm.test(“Assert ‘id’ Is Greater Than 0”, function () { // Match numbers pm.expect(resData.id).to.match(/^\d+$/i) }); pm.test(“Assert ‘company’ Is Not Null”, function () { pm.expect(resData.company).to.be.not.null }); pm.test(“Assert ‘name’ Is ‘Esau Silva'”, function () { pm.expect(resData.name).to.be.eql(‘Esau Silva’) }); To run the tests click on the ellipsis of the collection on the left panel, select “Run“, and finally click the “Run” button. You will see the passing results in the following screen after running the collection. You might be asking, where is this useful? Well, this can be extremely useful as the last step of your CI/CD pipeline after deployment to DEV and/or UAT environments. You can validate that nothing was broken after your latest deployment, API contracts stayed the same, and no unexpected/unintentional behavior was introduced. In Azure DevOps, you can install newman CLI NPM package to run the Postman collection and fail the deployment if one of the test scenarios fails. Now, say you have error validation responses, which ideally you are returning a 404 HTTP Status Code along with a Problem Details response. You could write something like this: // Get the request response var res = pm.response var resData = pm.response.json() // Test assetions pm.test(“Assert HTTP Status = 404 Not Found”, function () { res.to.have.status(404) }); pm.test(“Assert ‘error’ Message”, function () { pm.expect(resData.message).to.be.eql(‘Not Found’) }); In this case, I misspelled the username route in the following request: https://api.github.com/users/xesausilva then test for the expected failure response. Setting Postman Variables Dynamically Say you have several requests that need to be called one after another where the previous response is needed for input for the following request. You can set Postman Collection Variables under the “Scripts -> Post-response” tab as well as below: /* In this example, I’m hard-coding the variable, but in a potential real use case, you can use a response value to populate the variable, say “resData.id” */ // Create `anime` collection variable and set it for // the next request pm.collectionVariables.set(‘user_gists’, ‘gists’) Then for the following request, you can use that variable in the following format: {{user_gists}}. Like so https://api.github.com/users/esausilva/{{user_gists}}  A note side note here, you can also use Collection Variables in the body of the request as well. Sometimes, you need to generate a random variable BEFORE you execute a request, and this variable does not depend on a previous request. For this scenario, you set it under the “Scripts -> Pre-request” tab. You could write something like this function randomNumber(min, max) { return Math.floor(Math.random() * (max – min + 1)) + min; } var routes = [’followers’,’gists’,’following’,’starred’,’orgs’] // Create `routes` collection variable and assign a // random route title from `routes` array pm.collectionVariables.set( ‘routes’, routes[randomNumber(0,4)] ) Then use the routes variable like so https://api.github.com/users/esausilva/{{routes}}  Now, before each request call, Postman will assign a random route from the given list and call the API. How is this useful? Say a request needs to be called with a unique value to avoid hitting idempotency, this way you can generate a random integer or a GUID to send in the request. Performance / Load Testing with Postman In one of my previous posts, I describe how Postman can be used to run performance/load testing: https://payments.ingomoney.com/developer-blog/run-load-performance-testing-with-postman/  But what I want to point out here is that Postman exposes the iteration number in the following property var iteration = pm.info.iteration iteration property will be “0” the first time and increments each time the script runs under a load testing scenario. This can be useful when we want to set some variable based on the iteration number. A real-life use case: I was testing idempotency in one of our APIs and needed a way to tell Postman to alternate between using the same request id field and a new one. By making use of the iteration property, I was calling the API with the same ID on even iteration numbers and a new one on odd iteration numbers. I hope you were able to learn something new and are ready to use Postman to its fullest in your day-to-day work.

Unintended Side Effects with .NET Core Service Lifetimes and Dependency Injection (DI)

March 5, 2025 By Esau Silva

We have an API that handles ~45k monthly requests that occasionally responded strangely. I suspected it was related to the .NET Core service lifetimes. The symptoms in question were that, out of the blue, the API response body included a status code of 409 with a message of “invalid user-provided values”; however, the actual HTTP response status code was 200. From then on, the API would respond with the same invalid body, no matter what the request was. To give a little background, the API is deployed on-premises as multiple instances of Windows services. And the fix? Well, the fix for this issue was to simply restart the Windows services. After the restart, the API would start responding as expected. Finding the IssueAfter debugging and stepping through the code locally, I reached a base class holding a list of validations for the Domain Entities  (IList<SpecificationValidationResult> _validationResults = new List<SpecificationValidationResult>()). It was here that I noticed this list was holding validations throughout the application’s lifetime—in other words, a singleton instance of the validator class. The problem? Well, if a validation result reached an invalid state, the list would hold this invalid state for any future requests, returning a failure upon list evaluation. Fixing The Service LifetimesUpon looking at the Dependency Injection (DI) configurations, I noticed the validator was being configured as Transcient; however, the services running the configurations were configured as Singleton. This means that upon the singleton services receiving the first request, they would instantiate the validator for the first time and keep the same instance throughout the service lifetime. The original intention of having the validators be Transcient was to have one validator instance per HTTP request. However, running a Transient service from within a Singleton service will effectively make the Transcient service a Singleton. Refactoring the validators as Scoped and the services to Transcient fixed the issue. It gave the validators back their original intent, which was to live only the duration of the HTTP request. Moral of the Story Make sure you are implementing the correct DI for your use case and test the application thoroughly before deploying! There are plenty of tutorials out there that show how .NET Core service lifetimes and Dependency Injection (DI) work, however, the most useful one I have found is “Dependency Injection Deep Dive” by Amichai Mantinband https://youtu.be/yjUCKSKCQxg?si=oSnza8jZpk4x9PMS”. Have you run into any issues regarding service lifetimes? Let me know in the comments below!

Run Load (Performance) Testing with Postman

March 5, 2025 By Esau Silva

I recently found that Postman has a built-in capability to run load (performance) testing. Some use cases to run load testing are identifying bottlenecks, latency, and failures in your API when calling at near-production scale. One of the advantages of Postman having built-in load testing is that I already have collections/environments for all of my APIs in Postman. So, I do not have to use a different tool for the job or migrate scripts to another platform. I have used load testing a few times at work: One of our APIs had slow responses in production. I did a re-implementation and load-tested the API locally as well as in our development and UAT environments with Postman, both pre- and post-implementation. Another instance occurred after implementing idempotency on another of our APIs. Several scenarios were tested: The first call goes through successfully. Subsequent calls return an in-flight or in-progress transaction. Once the first call finishes, subsequent calls return idempotent responses. Running Performance TestingSelect the Postman collection to perform the performance testing, click the three dots at the top right, and then click “Run Collection.” Select the scripts to run the performance testing on. Select the “Performance” tab on the right. There will be three options: Max Virtual Users: How many “users” will run simultaneously calling the collection. Test Duration: How long the testing will last. Load Profile: If all “users” will start calling the API at the same time (Fixed) or if there will be a Ramp Up time where all “users” will start calling the API after a period of time. After the test has finished running, you will get a nice graph with detailed results. Some statistics include the total number of requests, requests per second, response times, and errors, if any. If errors are present, you can see detailed responses, status codes, etc. When you select a particular collection, you can press the “Runs” tab to see past runs, then select a particular run to see details. I hope you learned something about load/performance testing and start applying this technique to test your APIs. Have you had any experience with load/performance testing and have you used Postman for this? JMeter maybe?