<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged apitesting</title>
<link>https://coderlegion.com/tag/apitesting</link>
<description>Powered by Question2Answer</description>
<item>
<title>The fastest way I know to poke an endpoint</title>
<link>https://coderlegion.com/21994/the-fastest-way-i-know-to-poke-an-endpoint</link>
<description>&lt;p&gt;Most of my API checks are embarrassingly small. Is staging up? Does this endpoint still return the field the frontend expects? Did the auth header fix actually deploy? For work that small, opening Postman feels like bringing a truck to carry one grocery bag, and curl means fifteen seconds of remembering whether it's &lt;code&gt;-H&lt;/code&gt; or &lt;code&gt;-d&lt;/code&gt; that wants the quotes.&lt;/p&gt;
&lt;p&gt;So this lives in a browser tab now: &lt;a rel=&quot;nofollow&quot; href=&quot;https://catssaymeow.org/api-client/&quot;&gt;catssaymeow.org/api-client&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16835165599182027344&quot; alt=&quot;The API Client request form&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pick a method, paste a URL, add headers and a body if the call needs them, send. The response comes back as one readable unit: status code, timing, headers, and body, with the JSON already pretty-printed. Nothing to install, no account, no workspace to name.&lt;/p&gt;
&lt;p&gt;One detail that earns its keep: the URL field also accepts a full cURL string. Copy a request out of a bug ticket or a browser's &quot;Copy as cURL&quot;, paste it in, and the method, headers, and body populate themselves.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;api-client-03-post-201-response.png&quot; alt=&quot;A POST request with a JSON body returning 201 Created&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-part-i-actually-built-it-for&quot;&gt;The part I actually built it for&lt;/h3&gt;
&lt;p&gt;Half the time someone wants to try an API tool, they don't have an endpoint handy. Staging is down, the ticket hasn't landed, or they're teaching someone what a 401 even is.&lt;/p&gt;
&lt;p&gt;The Practice API covers that case. It's a mock REST API that runs client-side in the page, with seeded &lt;code&gt;/users&lt;/code&gt; and &lt;code&gt;/posts&lt;/code&gt; collections and one-click examples grouped by intent: read, write, delete, meta.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16251391635524080930&quot; alt=&quot;The Practice API example picker&quot;&gt;&lt;/p&gt;
&lt;p&gt;The examples aren't just happy paths. There's a 404 for a missing record, a 401 for a protected route without a token, a 204 with no body, an OPTIONS preflight. Every status a junior tester will meet in their first month, reproducible on demand.&lt;/p&gt;
&lt;p&gt;And the mock is stateful within the page. POST a new user, then GET the collection, and the new record is there:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=2208636266618461727&quot; alt=&quot;GET /users returning the record created by the previous POST&quot;&gt;&lt;/p&gt;
&lt;p&gt;That's the difference between a demo and a practice environment. Reloading the page resets everything, so there's nothing to clean up and no way to break it for the next person.&lt;/p&gt;
&lt;h3 id=&quot;the-boring-but-important-part&quot;&gt;The boring but important part&lt;/h3&gt;
&lt;p&gt;Real requests route through a server-side proxy with layered SSRF protections, rate limiting, and per-host circuit breakers, so the tool can't be pointed at internal infrastructure. Practice API requests never touch the network at all; the responses are generated in the page, and the response panel labels them &quot;Simulated&quot; so there's no confusion about what was real.&lt;/p&gt;
&lt;p&gt;It works on a phone, too, which has saved me at least once when a deploy check couldn't wait for a laptop.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=1092795168464127536&quot; alt=&quot;The API Client on a 390px mobile viewport&quot;&gt;&lt;/p&gt;
&lt;p&gt;If a quick endpoint check is on today's list, it's at &lt;a rel=&quot;nofollow&quot; href=&quot;https://catssaymeow.org/api-client/&quot;&gt;catssaymeow.org/api-client&lt;/a&gt;. Free, no signup, and the Practice API is there when the real endpoint isn't.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21994/the-fastest-way-i-know-to-poke-an-endpoint</guid>
<pubDate>Mon, 06 Jul 2026 09:27:20 +0000</pubDate>
</item>
<item>
<title>I Was Tired of Installing API Tools Just to Test One Endpoint — So I Found Something Better</title>
<link>https://coderlegion.com/19604/i-was-tired-of-installing-api-tools-just-to-test-one-endpoint-so-i-found-something-better</link>
<description>&lt;p&gt;Let me paint you a picture.&lt;/p&gt;
&lt;p&gt;It's 11 PM. You're integrating a third-party payment API into your app. The documentation is decent, but something isn't working — you keep getting a &lt;code&gt;401 Unauthorized&lt;/code&gt; back, and you have no idea if it's your token, your headers, or just the universe conspiring against you.&lt;/p&gt;
&lt;p&gt;Your options? Fire up Postman (which you haven't opened in three weeks and now wants to update), install Insomnia (if you remember your account password), or try writing a quick curl command in the terminal — knowing full well you'll mess up the escaping on the JSON body and spend another 20 minutes Googling why.&lt;/p&gt;
&lt;p&gt;There's a fourth option. One that requires zero installs, zero accounts, and zero patience for setup.&lt;/p&gt;
&lt;p&gt;But before we get there — let's actually talk about REST APIs, because if you're new to this world, a lot of it can feel unnecessarily mysterious.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-even-is-a-rest-api-&quot;&gt;What Even Is a REST API?&lt;/h3&gt;
&lt;p&gt;Here's the non-textbook version: a REST API is just a way for two systems to talk to each other over the internet using standard web rules.&lt;/p&gt;
&lt;p&gt;When you open Instagram and your feed loads — that's your app making an API call to Instagram's servers. When you book a flight and your seat gets confirmed — that's an API call going to the airline's backend. When Slack notifies you of a new message on your phone — you guessed it.&lt;/p&gt;
&lt;p&gt;REST stands for &lt;strong&gt;Representational State Transfer&lt;/strong&gt;, which sounds incredibly academic and not particularly useful to know. What matters is the practical part: REST APIs use regular HTTP (the same protocol your browser uses), they deal in &lt;strong&gt;resources&lt;/strong&gt; (think: users, orders, products), and they communicate mostly in &lt;strong&gt;JSON&lt;/strong&gt; — a format that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;user&quot;: &quot;sadiq&quot;,
  &quot;status&quot;: &quot;active&quot;,
  &quot;plan&quot;: &quot;pro&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clean. Human-readable. Easy to work with.&lt;/p&gt;
&lt;p&gt;The other thing you need to know is that REST APIs use &lt;strong&gt;HTTP methods&lt;/strong&gt; to express intent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GET&lt;/strong&gt; — &quot;Give me something.&quot; Fetching a list of users, loading a profile, retrieving an order.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;POST&lt;/strong&gt; — &quot;Create something new.&quot; Submitting a form, registering an account, placing an order.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PUT&lt;/strong&gt; — &quot;Replace this thing entirely.&quot; Updating a user's full profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PATCH&lt;/strong&gt; — &quot;Just change this one part.&quot; Updating only the email address on a profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DELETE&lt;/strong&gt; — &quot;Get rid of this.&quot; Removing a record.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These five methods cover about 99% of what you'll encounter in real-world API work. The other two — &lt;strong&gt;HEAD&lt;/strong&gt; and &lt;strong&gt;OPTIONS&lt;/strong&gt; — are more behind-the-scenes, usually used for checking if a resource exists or for CORS preflight checks.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-problem-with-testing-apis&quot;&gt;The Problem With Testing APIs&lt;/h3&gt;
&lt;p&gt;Here's something nobody talks about enough: &lt;strong&gt;testing APIs is just hard enough to be annoying&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It's not hard like writing a compiler or implementing a sorting algorithm. It's hard in a friction-filled, setup-heavy, &quot;why am I spending 20 minutes on this&quot; kind of way.&lt;/p&gt;
&lt;p&gt;If you're a backend developer, you probably have curl muscle memory by now. But curl is unforgiving — one misplaced quote or escaped character and your beautifully crafted JSON body turns into garbage. And reading curl output when something goes wrong? Not exactly a pleasant experience.&lt;/p&gt;
&lt;p&gt;Postman is the gold standard for a lot of teams, and for good reason — it's powerful. But powerful also means complex. Collections, environments, workspaces, team sync — it's a lot when you just want to fire off a quick request to see if an endpoint returns what it's supposed to. There's also the matter of it being a desktop app you need to install, update, and sometimes log into.&lt;/p&gt;
&lt;p&gt;The other issue that catches developers off-guard — especially those newer to frontend work — is &lt;strong&gt;CORS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;CORS (Cross-Origin Resource Sharing) is a browser security feature that blocks your JavaScript from calling APIs on different domains unless the API explicitly says &quot;yes, this domain can talk to me.&quot; It exists for genuinely good reasons (preventing malicious websites from making requests on your behalf), but it's also the source of an enormous amount of confusion and pain.&lt;/p&gt;
&lt;p&gt;You'll write what looks like perfect code. You'll test it. You'll get a wall of red text in your browser console that says something like &lt;code&gt;Access to fetch at 'https://api.example.com' from origin 'http://localhost:3000' has been blocked by CORS policy&lt;/code&gt;. And you'll wonder if you've done something horribly wrong.&lt;/p&gt;
&lt;p&gt;You haven't. The API just doesn't allow browser-based requests from your origin. It'll work fine server-to-server — which is exactly why a server-side testing tool is so much more useful than a browser-based one.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;meet-the-tool-that-actually-fixes-this&quot;&gt;Meet the Tool That Actually Fixes This&lt;/h3&gt;
&lt;p&gt;There's a free online REST API tester over at &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com&quot;&gt;sadiqbd.com&lt;/a&gt; — specifically the &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com/developer/rest-api-checker&quot;&gt;REST API Checker&lt;/a&gt; — and honestly, it's become one of those tools I didn't know I needed until I started using it.&lt;/p&gt;
&lt;p&gt;The concept is simple: you paste in your API URL, choose your method, add any headers or a request body, and hit &lt;strong&gt;Send&lt;/strong&gt;. Within seconds you get back the full response — status code, response headers, response body (pretty-printed if it's JSON), and the time it took.&lt;/p&gt;
&lt;p&gt;What makes it different from just opening your browser's Network tab is the &lt;strong&gt;server-side proxying&lt;/strong&gt;. When you use this tool, the request doesn't come from your browser — it comes from their server. That completely bypasses CORS. It doesn't matter if the API has restrictive CORS headers or none at all. You'll get the real response, every time.&lt;/p&gt;
&lt;p&gt;Let me walk through what it actually supports:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HTTP Methods:&lt;/strong&gt; GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. Every method you'll realistically need.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom Headers:&lt;/strong&gt; Add as many as you need. Authorization tokens, Content-Type overrides, custom API keys — any header the API expects, you can set it. The Authorization header field especially comes in handy when you're debugging authentication: &lt;code&gt;Bearer your-token-here&lt;/code&gt; goes in just like you'd set it in code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Request Body Formats:&lt;/strong&gt; Three options — JSON (which auto-sets &lt;code&gt;Content-Type: application/json&lt;/code&gt;), raw (for XML, plain text, or anything else), and multipart form-data (for file uploads). This is actually comprehensive enough to cover most real-world API testing scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Response Details:&lt;/strong&gt; You get the status code, response time, body size, all response headers, and the formatted body. If the API returns JSON, it's automatically prettified so you can actually read it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;real-scenarios-where-this-saves-time&quot;&gt;Real Scenarios Where This Saves Time&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Scenario 1: You're integrating a new API and want to verify it works before writing any code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the fastest use case. Copy the example request from the documentation, paste it in, run it. If it returns what the docs say it should, you know the API is working and your credentials are valid. Now you can write code with confidence.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scenario 2: Something's broken in production and you need to isolate whether it's your code or the API.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hit the API directly from the tester with the same payload your code sends. If it works there but not in your app, the bug is in your code. If it fails there too, the API is the problem. Five seconds of testing that would have taken you 20 minutes to debug otherwise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scenario 3: You're getting a 400 Bad Request and have no idea why.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is where the response body matters. Most well-designed APIs return a JSON error object explaining what went wrong — missing field, wrong data type, invalid value. The pretty-printed response makes this readable immediately. Common culprits: missing required fields, wrong data types, or subtly malformed JSON (a trailing comma that's valid in JavaScript but not in strict JSON parsers).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scenario 4: You're testing a webhook.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Webhooks are notoriously painful to debug. With this tool, you can replay a webhook payload to your endpoint and see exactly what it returns — useful for reproducing intermittent failures or testing your error handling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scenario 5: Comparing staging vs. production.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Swap the URL, keep everything else the same. If staging returns something different from production, you've found your environment drift. This kind of quick comparison is surprisingly hard to do cleanly with other tools.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;a-few-things-worth-knowing&quot;&gt;A Few Things Worth Knowing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;On API key safety:&lt;/strong&gt; The tool doesn't store your request bodies, headers, or responses. That said, for genuinely sensitive production credentials — the ones that control real money or user data — it's wise to use scoped test keys or short-lived tokens. Not because this tool is untrustworthy, but because that's just good security hygiene regardless of what tool you're using.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On private/internal APIs:&lt;/strong&gt; Since requests are made server-side, they need to reach a publicly accessible URL. Private IPs and loopback addresses (localhost, 192.168.x.x, etc.) are blocked for security reasons. For internal APIs, you'd need a tunneling tool like ngrok to expose them temporarily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On file uploads:&lt;/strong&gt; The multipart form-data option supports file attachments up to 5 MB each. That covers most practical file upload API testing scenarios — image upload endpoints, document imports, that kind of thing.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;beyond-rest-api-testing&quot;&gt;Beyond REST API Testing&lt;/h3&gt;
&lt;p&gt;While you're on &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com&quot;&gt;sadiqbd.com&lt;/a&gt;, it's worth knowing the site is actually a full toolkit for developers and beyond. The developer section alone has a JSON Formatter (genuinely one of the most-used tools when working with APIs), a JWT Decoder (paste in any JWT and instantly see the header, payload, and expiry), a Regex Tester, Hash Generator, Base64 Encoder/Decoder, and more.&lt;/p&gt;
&lt;p&gt;There are also internet tools for DNS lookups, SSL checking, HTTP header inspection, and port scanning — the kind of things you end up Googling every few weeks and wishing were in one place.&lt;/p&gt;
&lt;p&gt;It's the sort of site that earns a browser bookmark pretty quickly.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-bigger-picture&quot;&gt;The Bigger Picture&lt;/h3&gt;
&lt;p&gt;Here's what I actually think about when I look at a tool like this: the best developer tools are the ones that collapse friction.&lt;/p&gt;
&lt;p&gt;The gap between &quot;I want to test this API&quot; and &quot;I have my test result in front of me&quot; should be as small as possible. Every minute spent setting up a client, remembering a password, updating software, or wrestling with a curl command is a minute not spent on the actual problem you're trying to solve.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com/developer/rest-api-checker&quot;&gt;REST API Checker on sadiqbd.com&lt;/a&gt; doesn't do everything Postman does. It doesn't have saved collections or team collaboration or automated test suites. But it does the thing you need most of the time — send a request, see the response — with literally zero friction. Open a tab, paste a URL, click Send.&lt;/p&gt;
&lt;p&gt;That's it.&lt;/p&gt;
&lt;p&gt;For the quick tests, the late-night debugging sessions, the &quot;let me just verify this works before I write the integration&quot; moments — it's hard to beat.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;REST APIs are everywhere. Understanding them — even at a surface level — makes you dramatically more effective as a developer, whether you're building backends, working on frontend integrations, or just trying to make sense of why something isn't working.&lt;/p&gt;
&lt;p&gt;And having a fast, reliable, no-fuss way to test them? That's not a luxury. It's just practical.&lt;/p&gt;
&lt;p&gt;Bookmark &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com/developer/rest-api-checker&quot;&gt;sadiqbd.com/developer/rest-api-checker&lt;/a&gt;. You'll use it more than you expect.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Found this useful? The full suite of developer tools — JSON formatter, JWT decoder, regex tester, and more — lives at &lt;a rel=&quot;nofollow&quot; href=&quot;https://sadiqbd.com&quot;&gt;sadiqbd.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/19604/i-was-tired-of-installing-api-tools-just-to-test-one-endpoint-so-i-found-something-better</guid>
<pubDate>Wed, 03 Jun 2026 18:41:12 +0000</pubDate>
</item>
<item>
<title>I Built a Free JSON Karate DSL Schema Generator for QA Engineers</title>
<link>https://coderlegion.com/17319/i-built-a-free-json-karate-dsl-schema-generator-for-qa-engineers</link>
<description>&lt;p&gt;If you work with &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://karatelabs.github.io/karate/?utm_source=chatgpt.com&quot;&gt;Karate DSL&lt;/a&gt;&lt;/strong&gt; for API testing, you already know how important and useful schema validation can be.&lt;/p&gt;
&lt;p&gt;You also know how repetitive it becomes.&lt;/p&gt;
&lt;p&gt;Writing Karate match schemas manually for every API response is one of those tasks that feels small at first until you start working with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deeply nested JSON responses&lt;/li&gt;
&lt;li&gt;arrays of objects&lt;/li&gt;
&lt;li&gt;large payloads&lt;/li&gt;
&lt;li&gt;optional fields&lt;/li&gt;
&lt;li&gt;multiple endpoints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After doing this repeatedly in real automation projects, I decided to build a small utility focused on solving exactly that problem.&lt;/p&gt;
&lt;p&gt;So I created a free browser-based tool:&lt;/p&gt;
&lt;h3 id=&quot;json-karate-dsl-schema-converter&quot;&gt;JSON → Karate DSL Schema Converter&lt;/h3&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://jsonkaratedslgenerator.codeqazone.com/&quot;&gt;https://jsonkaratedslgenerator.codeqazone.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The tool instantly converts a JSON payload into a ready-to-use Karate DSL schema.&lt;/p&gt;
&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;/h3&gt;
&lt;p&gt;Karate DSL does not use traditional JSON Schema syntax.&lt;/p&gt;
&lt;p&gt;Instead, it uses type matchers like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&quot;#string&quot;
&quot;#number&quot;
&quot;#boolean&quot;
&quot;#[]&quot;
&quot;##string&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That approach is powerful and very readable once you understand it.&lt;/p&gt;
&lt;p&gt;But manually transforming a real API response into a Karate validation schema can become repetitive and time-consuming.&lt;/p&gt;
&lt;p&gt;For example, a response like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;id&quot;: 101,
  &quot;name&quot;: &quot;Alice&quot;,
  &quot;active&quot;: true,
  &quot;roles&quot;: [&quot;admin&quot;, &quot;user&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usually becomes something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  &quot;id&quot;: &quot;#number&quot;,
  &quot;name&quot;: &quot;#string&quot;,
  &quot;active&quot;: &quot;#boolean&quot;,
  &quot;roles&quot;: &quot;#[] #string&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that is a very small example.&lt;/p&gt;
&lt;p&gt;In real-world APIs, payloads can be much larger and more nested.&lt;/p&gt;
&lt;h3 id=&quot;what-the-tool-does&quot;&gt;What the Tool Does&lt;/h3&gt;
&lt;p&gt;The converter takes a JSON payload and automatically generates a Karate-compatible schema while preserving the original structure.&lt;/p&gt;
&lt;p&gt;It supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;primitive types&lt;/li&gt;
&lt;li&gt;nested objects&lt;/li&gt;
&lt;li&gt;arrays&lt;/li&gt;
&lt;li&gt;arrays of objects&lt;/li&gt;
&lt;li&gt;nested arrays&lt;/li&gt;
&lt;li&gt;optional fields&lt;/li&gt;
&lt;li&gt;copy to clipboard&lt;/li&gt;
&lt;li&gt;schema download&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything runs directly in the browser.&lt;/p&gt;
&lt;p&gt;No installation.&lt;br&gt;
No backend.&lt;br&gt;
No data storage.&lt;/p&gt;
&lt;p&gt;Just paste your JSON and generate the schema instantly.&lt;/p&gt;
&lt;h3 id=&quot;example-conversion&quot;&gt;Example Conversion&lt;/h3&gt;
&lt;h4 id=&quot;input-json&quot;&gt;Input JSON&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;id&quot;: 101,
  &quot;name&quot;: &quot;Alice&quot;,
  &quot;active&quot;: true,
  &quot;user&quot;: {
    &quot;email&quot;: &quot;*Emails are not allowed*&quot;,
    &quot;profile&quot;: {
      &quot;age&quot;: 30,
      &quot;verified&quot;: true
    }
  },
  &quot;orders&quot;: [
    {
      &quot;orderId&quot;: 1,
      &quot;amount&quot;: 99.99
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;generated-karate-schema&quot;&gt;Generated Karate Schema&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  &quot;id&quot;: &quot;#number&quot;,
  &quot;name&quot;: &quot;#string&quot;,
  &quot;active&quot;: &quot;#boolean&quot;,
  &quot;user&quot;: {
    &quot;email&quot;: &quot;#string&quot;,
    &quot;profile&quot;: {
      &quot;age&quot;: &quot;#number&quot;,
      &quot;verified&quot;: &quot;#boolean&quot;
    }
  },
  &quot;orders&quot;: &quot;#[] {\&quot;orderId\&quot;:\&quot;#number\&quot;,\&quot;amount\&quot;:\&quot;#number\&quot;}&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;required-vs-optional-fields&quot;&gt;Required vs Optional Fields&lt;/h3&gt;
&lt;p&gt;One thing I intentionally wanted in the tool was explicit control over required and optional fields in the schema.&lt;/p&gt;
&lt;p&gt;Instead of automatically guessing business rules, the tool lets the tester define which fields are required.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;id, name, user.email
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fields included in that input remain required while all other fields are automatically converted into optional Karate matchers using the &lt;code&gt;##&lt;/code&gt; syntax.&lt;/p&gt;
&lt;p&gt;That decision came directly from real QA workflows.&lt;/p&gt;
&lt;p&gt;As testers, we usually already know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which fields are mandatory&lt;/li&gt;
&lt;li&gt;which fields are conditional&lt;/li&gt;
&lt;li&gt;which fields depend on business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tool is not trying to replace that understanding, it is simply removing the repetitive manual work.&lt;/p&gt;
&lt;h3 id=&quot;why-i-built-it&quot;&gt;Why I Built It&lt;/h3&gt;
&lt;p&gt;This project came from real automation work. The goal was not to create a massive platform, it was to create something:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fast&lt;/li&gt;
&lt;li&gt;practical&lt;/li&gt;
&lt;li&gt;useful immediately&lt;/li&gt;
&lt;li&gt;frictionless to use&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A tool you can open, use in seconds, and continue with your work.&lt;/p&gt;
&lt;h3 id=&quot;features&quot;&gt;Features&lt;/h3&gt;
&lt;p&gt;Current features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JSON → Karate DSL conversion&lt;/li&gt;
&lt;li&gt;Required fields input&lt;/li&gt;
&lt;li&gt;Optional field generation (&lt;code&gt;##type&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Nested object support&lt;/li&gt;
&lt;li&gt;Array schema generation&lt;/li&gt;
&lt;li&gt;Demo examples&lt;/li&gt;
&lt;li&gt;Copy-to-clipboard support&lt;/li&gt;
&lt;li&gt;Schema download&lt;/li&gt;
&lt;li&gt;Browser-only execution&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-is-this-for-&quot;&gt;Who Is This For?&lt;/h3&gt;
&lt;p&gt;This tool is especially useful for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;QA Automation Engineers&lt;/li&gt;
&lt;li&gt;API Testers&lt;/li&gt;
&lt;li&gt;Developers using Karate DSL&lt;/li&gt;
&lt;li&gt;Teams building API validation suites&lt;/li&gt;
&lt;li&gt;People learning Karate schema validation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try It&lt;/h3&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://jsonkaratedslgenerator.codeqazone.com/&quot;&gt;https://jsonkaratedslgenerator.codeqazone.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The app also includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base Demo&lt;/li&gt;
&lt;li&gt;Advanced Demo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;so you can immediately understand how the conversion works.&lt;/p&gt;
&lt;p&gt;If you work with &lt;a rel=&quot;nofollow&quot; href=&quot;https://karatelabs.github.io/karate/?utm_source=chatgpt.com&quot;&gt;Karate DSL&lt;/a&gt;, I hope this tool saves you some time. Feedback and suggestions are always welcome.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Happy Testing!&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/17319/i-built-a-free-json-karate-dsl-schema-generator-for-qa-engineers</guid>
<pubDate>Sun, 10 May 2026 18:34:28 +0000</pubDate>
</item>
<item>
<title>Voiden: curl meets Obsidian</title>
<link>https://coderlegion.com/15062/voiden-curl-meets-obsidian</link>
<description>&lt;p&gt;We open sourced Voiden: an offline API tool where requests live as executable Markdown and are versioned in Git.  Its built on Electron and its free. &lt;/p&gt;
&lt;p&gt;The original idea and inspiration is to combine the flexibility of Obsidian-style files or Jupyter notebooks with the practicality of curl. Instead of static API request forms, everything in the tool is composed with blocks (endpoint, auth, params, body) that can be added, reused, overridden, and stitched together across plain text markdown files. &lt;/p&gt;
&lt;p&gt;Since Open Sourcing, we got 11K installs, a lot of feedback and some committed and opinionated contributors. &lt;/p&gt;
&lt;p&gt;A few highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Programmable UI: Building API requests with blocks using slash commands (endpoints, headers, auth, params, etc.).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reusable blocks: These blocks can be connected to (and reused by) multiple docs. Change a value once, update everywhere. Just like in code when we add an extra logic to an imported method. (In other API clients you would need to duplicate stuff or just use environment variables to substitute.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specs, tests, and docs live together in executable Markdown . You can structure APIs, tests, and docs however you want and everything stays executable/runnable in the same place.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scripting: We have seen other API tools locking scripts into a constrained JS runtime. Voiden runs locally, that means you can use whatever is already on your machine (Node, Python, shell, etc.). So this feels like real scripting and not sandboxes. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple requests per file (mini workflows): Putting multiple requests in a single .void file turned out to be surprisingly useful. You can group full flows together (create-pay-confirm), or full CRUD cycles. The file becomes an executable workflow where docs and tests live together naturally, and you can run one request or the entire sequence end-to-end. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stitch (workflows across files): Instead of building large monolithic collections, workflows can be composed from smaller .void files. This way, Auth, setup, CRUD, etc. become pieces that can be reused and combined across contexts without duplication. This is still early and evolving.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agents: Added “skills” so tools like Claude or Codex can work directly with .void files using your own environment and subscriptions. Yeah, one of the perks of everything being file-based and Markdown-first. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also built an SDK for community plugins and spent time improving performance, reliability, and keyboard-first DX (Electron-based, so we have been careful there).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy to hear any feedback, suggestions and contributions!&lt;/p&gt;
&lt;p&gt;Github: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/VoidenHQ/voiden&quot;&gt;https://github.com/VoidenHQ/voiden&lt;/a&gt;&lt;br&gt;
Download: &lt;a rel=&quot;nofollow&quot; href=&quot;https://voiden.md/download&quot;&gt;https://voiden.md/download&lt;/a&gt;&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/15062/voiden-curl-meets-obsidian</guid>
<pubDate>Fri, 17 Apr 2026 11:07:47 +0000</pubDate>
</item>
<item>
<title>How This Tool Improves Developer Productivity with JSON and API Workflows</title>
<link>https://coderlegion.com/8480/how-this-tool-improves-developer-productivity-with-json-and-api-workflows</link>
<description>&lt;p&gt;JSON is the de facto data interchange format for modern web and mobile applications. However, generating, validating, and maintaining JSON structures manually can introduce friction in development workflows, particularly during rapid prototyping and API development.&lt;/p&gt;
&lt;p&gt;Automated JSON Structure Generation&lt;/p&gt;
&lt;p&gt;The tool converts natural-language descriptions into syntactically valid, well-structured JSON. It automatically handles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Proper nesting of objects and arrays&lt;/li&gt;
&lt;li&gt;List item Consistent key naming&lt;/li&gt;
&lt;li&gt;Appropriate primitive and composite data types&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This reduces human error and eliminates repetitive boilerplate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API-Ready Response Generation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Generated output can be used directly as mock API responses. This enables frontend teams to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Develop UI components independently of backend availability Simulate&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API contracts early in the development cycle Validate response&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;schemas before backend implementation&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach aligns well with contract-first and API-driven development methodologies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By automating JSON generation and validation while supporting downstream API workflows, this tool reduces development overhead and accelerates iteration cycles, allowing engineers to focus on system design and business logic rather than data scaffolding.&lt;/p&gt;
&lt;p&gt;Reference tool:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://formatjsononline.com/ai-json-generator&quot;&gt;https://formatjsononline.com/ai-json-generator&lt;/a&gt;&lt;/p&gt;
</description>
<category>Java</category>
<guid isPermaLink="true">https://coderlegion.com/8480/how-this-tool-improves-developer-productivity-with-json-and-api-workflows</guid>
<pubDate>Mon, 15 Dec 2025 10:12:51 +0000</pubDate>
</item>
<item>
<title>Stop Mocking Everything: How to Test API Resilience in Your Terminal (Curl + Chaos Proxy)</title>
<link>https://coderlegion.com/8178/stop-mocking-everything-how-to-test-api-resilience-in-your-terminal-curl-chaos-proxy</link>
<description>&lt;p&gt;&quot;It works on my machine.&quot;&lt;/p&gt;
&lt;p&gt;We've all said it. But does your bash script work when the third-party API takes 15 seconds to respond? Does your backend service gracefully handle a sudden spike of 503 errors from a payment provider?&lt;/p&gt;
&lt;p&gt;Writing a full mock server just to test a simple retry logic in a script is often overkill. In this tutorial, I'll show you a faster way: &lt;strong&gt;Chaos Engineering directly in the terminal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We will use &lt;code&gt;curl&lt;/code&gt; and a cloud-based Chaos Proxy to inject failures into real network requests without changing a single line of your application code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Problem: Localhost is Too Perfect&lt;/strong&gt;&lt;br&gt;
When developing locally, network latency is near zero. APIs either work (200 OK) or they don't (Connection Refused). But in production, you face:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;High Latency&lt;/strong&gt;: The server is busy.&lt;br&gt;
&lt;strong&gt;Intermittent Failures&lt;/strong&gt;: 5% of requests drop.&lt;br&gt;
&lt;strong&gt;Throttling&lt;/strong&gt;: You hit the rate limit.&lt;/p&gt;
&lt;p&gt;Simulating this in a terminal usually involves complex &lt;code&gt;iptables&lt;/code&gt; rules or local tools like &lt;code&gt;tc&lt;/code&gt; (Traffic Control). There is an easier way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Solution: Cloud Chaos Proxy&lt;/strong&gt;&lt;br&gt;
Instead of configuring your OS, we will route specific requests through a proxy that &quot;breaks&quot; the traffic according to rules we define.&lt;/p&gt;
&lt;p&gt;I'll be using chaos-proxy.debuggo.app for this, but the concept applies to any programmable proxy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Guide (1:27)&lt;/strong&gt;&lt;br&gt;
Prefer watching? &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=x_S-guPwPEk&quot;&gt;Here is the 90-second workflow: &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step-by-Step Tutorial&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Define the Failure&lt;/strong&gt;&lt;br&gt;
First, we need to tell the proxy what to break.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &lt;code&gt;httpbin.org&lt;/code&gt; (or your API domain).&lt;/li&gt;
&lt;li&gt;Delay: &lt;code&gt;7 seconds&lt;/code&gt; (Simulate lag).&lt;/li&gt;
&lt;li&gt;Failure Rate: 1 (100% of requests will fail).&lt;/li&gt;
&lt;li&gt;Error Code: 503 Service Unavailable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. Trust the Certificate (The &quot;One-Time&quot; Setup)&lt;/strong&gt;&lt;br&gt;
Since we are intercepting HTTPS traffic, we need to trust the proxy's CA certificate.&lt;/p&gt;
&lt;p&gt;Download the &lt;code&gt;mitmproxy-ca-cert.pem&lt;/code&gt; from the dashboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MacOS:&lt;/strong&gt; Add it to Keychain Access -&amp;gt; System and set &quot;Always Trust&quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux:&lt;/strong&gt; Copy to /usr/local/share/ca-certificates/ and update.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. The Magic Command&lt;/strong&gt;&lt;br&gt;
Now, we use &lt;code&gt;curl&lt;/code&gt; with the &lt;code&gt;-x&lt;/code&gt; (proxy) flag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -v -x http://user:*Emails are not allowed*:13979 https://httpbin.org/get
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Understanding the Output&lt;/strong&gt;&lt;br&gt;
When you run this command multiple times:&lt;/p&gt;
&lt;p&gt;Scenario A (The Chaos): You'll notice the terminal &quot;hangs&quot; for 7 seconds (our delay). Then:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt; HTTP/1.1 500 Internal Server Error
&amp;lt; content-length: 56
&amp;lt; content-type: text/plain
...
Debuggo Chaos Injection: 500 Error
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Scenario B (Success)&lt;/strong&gt;: The other 50% of the time, the request passes through to the real server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt; HTTP/1.1 200 OK
...
{
  &quot;args&quot;: {}, 
  &quot;headers&quot;: { ... }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Real World Use Cases&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Testing CI Pipelines&lt;/strong&gt;: Verify that your deployment scripts don't crash if a dependency is slow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cron Jobs&lt;/strong&gt;: Ensure your nightly data sync retries correctly on failure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quick Sanity Checks&lt;/strong&gt;: Before pushing code, verify how the API client handles a 503 error.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
You don't need heavy infrastructure to test network resilience. A simple proxy setup allows you to inject chaos into any HTTP client—be it &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, or your Python/Node.js scripts.&lt;/p&gt;
&lt;p&gt;Happy Breaking! &lt;/p&gt;
</description>
<category>Getting Started</category>
<guid isPermaLink="true">https://coderlegion.com/8178/stop-mocking-everything-how-to-test-api-resilience-in-your-terminal-curl-chaos-proxy</guid>
<pubDate>Fri, 05 Dec 2025 07:15:00 +0000</pubDate>
</item>
<item>
<title>API Performance Testing with k6 - A Quick Start Guide</title>
<link>https://coderlegion.com/1062/api-performance-testing-with-k6-a-quick-start-guide</link>
<description>&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;The definition of a high-quality REST API application is an application that can operate well and perform well. The performance of the REST API can be measured by performance testing to ensure the application is operational, scalable, and reliable on many different workloads. From normal workloads up to unexpected heavy workloads.&lt;/p&gt;
&lt;h3 id=&quot;why-performance-testing-&quot;&gt;Why Performance Testing?&lt;/h3&gt;
&lt;p&gt;The performance testing provides some benefits during REST API development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ensuring the performance of the REST API meets the desired standards, especially in unexpected workloads.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Detecting performance bottlenecks earlier before it went to production.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-is-k6-&quot;&gt;What is k6?&lt;/h3&gt;
&lt;p&gt;Many tools can be used for performance testing. One of those is k6. k6 is a performance testing tool developed by Grafana Labs for conducting performance testing in various platforms like REST API and web applications. The k6 is a code-based tool which means the testing script is written in a Javascript code. The k6 can be utilized even more by using additional plugins and extensions.&lt;/p&gt;
&lt;h3 id=&quot;k6-setup&quot;&gt;k6 Setup&lt;/h3&gt;
&lt;p&gt;These are the required steps for using k6:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/set-up/install-k6/&quot;&gt;Install the k6&lt;/a&gt;. The k6 is available in Docker container and binary. Make sure to install it based on the operating system that is being used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/set-up/configure-your-code-editor/&quot;&gt;Configure the code editor&lt;/a&gt;. The code editor needs to be configured to enable the IntelliSense feature to enhance the developer experience when writing testing scripts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;writing-the-first-test&quot;&gt;Writing the First Test&lt;/h3&gt;
&lt;p&gt;The k6 testing scripts can be organized into one project because when working in a project, the scripts can be organized easily.&lt;/p&gt;
&lt;p&gt;Create the npm project by running this command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm init --yes
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;If you want to specify the additional information of the project, use &lt;code&gt;npm init&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After that, install the k6 types to enable the IntelliSense feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install --save-dev @types/k6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The test script can be generated automatically using the &lt;code&gt;k6 new&lt;/code&gt; command. This is the structure of the command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k6 new &amp;lt;directory_name&amp;gt;/filename.js
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;Make sure the &lt;code&gt;directory&lt;/code&gt; is exists.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the directory location is not specified. This command creates a test script in the current working directory. The test script can be created manually as well.&lt;/p&gt;
&lt;p&gt;This is the example of creating a new test script in the &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k6 new src/test.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the content of the created test script. The comments inside the test script is already removed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { sleep } from &quot;k6&quot;;

export const options = {
  // A number specifying the number of VUs to run concurrently.
  vus: 10,
  // A string specifying the total duration of the test run.
  duration: &quot;30s&quot;,
};

export default function () {
  http.get(&quot;https://test.k6.io&quot;);
  sleep(1);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The test can be executed using &lt;code&gt;k6 run&lt;/code&gt; command followed by the file name.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k6 run src/test.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the output of the test.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=5885088158197040425&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;After the test is executed, the k6 generates a summary output that describes information like the number of successful requests, duration of the requests, and others. &lt;br&gt;
A detailed explanation of the summary output is available &lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/using-k6/metrics/reference/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;load-testing-types&quot;&gt;Load Testing Types&lt;/h3&gt;
&lt;p&gt;There are many types of load testing for measuring the performance of the system. Each type serves different purposes and requirements.&lt;/p&gt;
&lt;h4 id=&quot;smoke-testing&quot;&gt;Smoke Testing&lt;/h4&gt;
&lt;p&gt;The smoke testing ensures the system is operational with a minimal load and verifies the test scripts. The smoke testing must be executed with a small number of virtual users (from 2 up to 5 VUs) and short duration.&lt;/p&gt;
&lt;p&gt;This is an example of smoke testing for getting all posts feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { check } from &quot;k6&quot;;

export const options = {
  vus: 3, // 3 virtual users
  duration: &quot;40s&quot;, // duration is 40 seconds
};

export default function () {
  // sends GET request
  const response = http.get(&quot;https://jsonplaceholder.typicode.com/posts&quot;);

  // validate the response
  check(response, {
    &quot;is status 200&quot;: (r) =&amp;gt; r.status === 200,
    &quot;is not null&quot;: (r) =&amp;gt; r.json() !== null,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;average-load-testing&quot;&gt;Average Load Testing&lt;/h4&gt;
&lt;p&gt;The average load testing ensures the system is operational with typical loads. Typical loads means the workload during the regular day in a production environment.&lt;/p&gt;
&lt;p&gt;This is the example of average load testing for getting all posts feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { check } from &quot;k6&quot;;

export const options = {
  stages: [
    { duration: &quot;5m&quot;, target: 100 }, // traffic ramp-up from 1 to 100 users over 5 minutes.
    { duration: &quot;30m&quot;, target: 100 }, // stay at 100 users for 30 minutes
    { duration: &quot;5m&quot;, target: 0 }, // ramp-down to 0 users
  ],
};

// function for generating random string
const generateRandomString = (start, end) =&amp;gt; {
  const res = Math.random().toString(36).substring(start, end);
  return res;
};

// function for generating random ID
const generateRandomId = () =&amp;gt; {
  const id = Math.floor(Math.random() * 1000);
  return id;
};

export default function () {
  // prepare request body
  const requestBody = {
    title: generateRandomString(1, 7),
    body: generateRandomString(1, 20),
    userId: generateRandomId(),
  };

  // sends POST request
  const response = http.post(
    &quot;https://jsonplaceholder.typicode.com/posts&quot;,
    JSON.stringify(requestBody),
    {
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
        Accept: &quot;application/json&quot;,
      },
    }
  );

  // validate the response
  check(response, {
    &quot;is status 201&quot;: (r) =&amp;gt; r.status === 201,
    &quot;is not null&quot;: (r) =&amp;gt; r.json() !== null,
    &quot;is contains valid id&quot;: (r) =&amp;gt; r.json().id &amp;gt; 0,
    &quot;is contains valid title&quot;: (r) =&amp;gt; r.json().title !== &quot;&quot;,
    &quot;is contains valid body&quot;: (r) =&amp;gt; r.json().body !== &quot;&quot;,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;stress-testing&quot;&gt;Stress Testing&lt;/h4&gt;
&lt;p&gt;The stress testing ensures the system is operational with heavier loads than usual. The stress testing verifies the stability and reliability of the system under heavy workloads. The system may receive heavy workloads in many moments such as flash-sale, payday, school or university admission process, and other similar moments. When conducting the stress testing, the number of workloads must be heavier than typical workloads and must be executed after average load testing.&lt;/p&gt;
&lt;p&gt;This is an example of stress testing for creating a new post feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { check } from &quot;k6&quot;;

export const options = {
  stages: [
    { duration: &quot;10m&quot;, target: 200 }, // traffic ramp-up from 1 to a higher 200 users over 10 minutes.
    { duration: &quot;30m&quot;, target: 200 }, // stay at higher 200 users for 30 minutes
    { duration: &quot;5m&quot;, target: 0 }, // ramp-down to 0 users
  ],
};

// function for generating random string
const generateRandomString = (start, end) =&amp;gt; {
  const res = Math.random().toString(36).substring(start, end);
  return res;
};

// function for generating random ID
const generateRandomId = () =&amp;gt; {
  const id = Math.floor(Math.random() * 1000);
  return id;
};

export default function () {
  // prepare request body
  const requestBody = {
    title: generateRandomString(1, 7),
    body: generateRandomString(1, 20),
    userId: generateRandomId(),
  };

  // sends POST request
  const response = http.post(
    &quot;https://jsonplaceholder.typicode.com/posts&quot;,
    JSON.stringify(requestBody),
    {
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
        Accept: &quot;application/json&quot;,
      },
    }
  );

  // validate the response
  check(response, {
    &quot;is status 201&quot;: (r) =&amp;gt; r.status === 201,
    &quot;is not null&quot;: (r) =&amp;gt; r.json() !== null,
    &quot;is contains valid id&quot;: (r) =&amp;gt; r.json().id &amp;gt; 0,
    &quot;is contains valid title&quot;: (r) =&amp;gt; r.json().title !== &quot;&quot;,
    &quot;is contains valid body&quot;: (r) =&amp;gt; r.json().body !== &quot;&quot;,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;spike-testing&quot;&gt;Spike Testing&lt;/h4&gt;
&lt;p&gt;The spike testing ensures the system is operational with suddenly heavy workloads. Example of sudden heavy workloads is product launch events, limited-time discount,s and others. During spike testing, the heavy workloads increased suddenly without any ramp-down or &quot;pause time&quot;.&lt;/p&gt;
&lt;p&gt;This is an example of spike testing for updating a post feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { check } from &quot;k6&quot;;

export const options = {
  stages: [
    { duration: &quot;2m&quot;, target: 500 }, // fast ramp-up without any break
    { duration: &quot;1m&quot;, target: 0 }, // quick ramp-down
  ],
};

// function for generating random string
const generateRandomString = (start, end) =&amp;gt; {
  const res = Math.random().toString(36).substring(start, end);
  return res;
};

// function for generating random ID
const generateRandomId = () =&amp;gt; {
  const id = Math.floor(Math.random() * 100);
  return id;
};

export default function () {
  const sampleId = generateRandomId();

  // prepare request body
  const requestBody = {
    title: generateRandomString(1, 7),
    body: generateRandomString(1, 20),
    userId: sampleId,
  };

  // sends PUT request
  const response = http.put(
    `https://jsonplaceholder.typicode.com/posts/${sampleId}`,
    JSON.stringify(requestBody),
    {
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
        Accept: &quot;application/json&quot;,
      },
    }
  );

  // validate the response
  check(response, {
    &quot;is status 200&quot;: (r) =&amp;gt; r.status === 200,
    &quot;is not null&quot;: (r) =&amp;gt; r.json() !== null,
    &quot;is contains valid id&quot;: (r) =&amp;gt; r.json().id &amp;gt; 0,
    &quot;is contains valid title&quot;: (r) =&amp;gt; r.json().title !== &quot;&quot;,
    &quot;is contains valid body&quot;: (r) =&amp;gt; r.json().body !== &quot;&quot;,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;endurance-testing&quot;&gt;Endurance Testing&lt;/h4&gt;
&lt;p&gt;The endurance testing (also known as soak testing) ensures the system is operational with average loads for a long duration. This test measures the performance degradation and the availability and stability during long periods.&lt;/p&gt;
&lt;p&gt;The endurance testing can be executed after the smoke and average load tests are executed. The duration of this test must be longer than any other kind of test.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Actually, the typical duration is in hours like 3,4,12 ,and up to 72 hours. For this example, the duration is reduced.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is an example of endurance testing for creating a post feature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import http from &quot;k6/http&quot;;
import { check } from &quot;k6&quot;;

export const options = {
  stages: [
    { duration: &quot;10m&quot;, target: 100 }, // traffic ramp-up from 1 to 100 users over 10 minutes.
    { duration: &quot;30m&quot;, target: 100 }, // stay at 100 users for 30 minutes
    { duration: &quot;10m&quot;, target: 0 }, // ramp-down to 0 users
  ],
};

// function for generating random string
const generateRandomString = (start, end) =&amp;gt; {
  const res = Math.random().toString(36).substring(start, end);
  return res;
};

// function for generating random ID
const generateRandomId = () =&amp;gt; {
  const id = Math.floor(Math.random() * 1000);
  return id;
};

export default function () {
  // prepare request body
  const requestBody = {
    title: generateRandomString(1, 7),
    body: generateRandomString(1, 20),
    userId: generateRandomId(),
  };

  // sends POST request
  const response = http.post(
    &quot;https://jsonplaceholder.typicode.com/posts&quot;,
    JSON.stringify(requestBody),
    {
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
        Accept: &quot;application/json&quot;,
      },
    }
  );

  // validate the response
  check(response, {
    &quot;is status 201&quot;: (r) =&amp;gt; r.status === 201,
    &quot;is not null&quot;: (r) =&amp;gt; r.json() !== null,
    &quot;is contains valid id&quot;: (r) =&amp;gt; r.json().id &amp;gt; 0,
    &quot;is contains valid title&quot;: (r) =&amp;gt; r.json().title !== &quot;&quot;,
    &quot;is contains valid body&quot;: (r) =&amp;gt; r.json().body !== &quot;&quot;,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;resources&quot;&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/set-up/install-k6/&quot;&gt;k6 Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/set-up/configure-your-code-editor/&quot;&gt;Configuring k6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/&quot;&gt;k6 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grafana.com/docs/k6/latest/testing-guides/test-types/&quot;&gt;Load Test Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nadirbasalamah/explore-k6&quot;&gt;Performance Testing with k6 Example Github Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I hope this article helps you to learn about API performance testing using k6.&lt;/p&gt;
&lt;p&gt;Do you have any experience working on performance testing using k6? Please let me know in the comments down below &lt;/p&gt;
&lt;p&gt;Thank you&lt;/p&gt;
</description>
<category>Performance</category>
<guid isPermaLink="true">https://coderlegion.com/1062/api-performance-testing-with-k6-a-quick-start-guide</guid>
<pubDate>Tue, 04 Feb 2025 06:36:54 +0000</pubDate>
</item>
<item>
<title>How to serialize JSON API requests using Java Records?</title>
<link>https://coderlegion.com/477/how-to-serialize-json-api-requests-using-java-records</link>
<description>&lt;p&gt;JSON is a popularly used file format in the APIs as it is lightweight and self-describing.&lt;br&gt;
JSON stands for JavaScript Object Notation and. It was derived from JavaScript and originally specified by &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.crockford.com/&quot;&gt;Douglas Crockford&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;JSON is easy to read, write, and language-independent, supporting data structures like arrays and objects for flexible organization. It is widely used by software teams and is a common choice for storing and transferring data. The RESTful APIs generally rely on JSON files to exchange data over HTTP.&lt;/p&gt;
&lt;p&gt;In this tutorial blog we will learn to serialize the JSON API requests using Java Records.&lt;/p&gt;
&lt;h3 id=&quot;what-are-java-records-&quot;&gt;What are Java Records?&lt;/h3&gt;
&lt;p&gt;A Java record is a special type of class designed specifically for working with immutable data. Java Records were introduced in Java 14 version as a preview feature and became a standard feature in Java 16. &lt;/p&gt;
&lt;p&gt;Records offer a concise syntax for defining classes primarily intended to store immutable data.&lt;/p&gt;
&lt;p&gt;The following is a simple example of Java Records:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public record Country(String name, long population) {
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;what-is-json-serialization-&quot;&gt;What is JSON Serialization?&lt;/h3&gt;
&lt;p&gt;JSON serialization is the process of transforming an object, data structure, or complex data type into a JSON (JavaScript Object Notation) format. For example, converting Java POJO into a JSON format. &lt;/p&gt;
&lt;p&gt;During JSON serialization, each attribute of an object is converted into a JSON property, while nested structures (such as lists or other objects) are represented as JSON arrays or nested JSON objects. This helps in making the data more portable and accessible to other systems, programming languages, or APIs.&lt;/p&gt;
&lt;p&gt;For example consider the following “Country” object using Java Records:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public record Country(String name, long population) {
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With JSON serialization, an instance of the “Country” Record could be converted to JSON as shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
&quot;name&quot; : &quot;India&quot;,
     &quot;population&quot;:  &quot;1.43 billion&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;how-to-serialize-json-api-requests-using-java-records-&quot;&gt;How to serialize JSON API Requests using Java Records?&lt;/h3&gt;
&lt;p&gt;API requests using request body in the JSON format can be serialized using Java Records easily through the Jackson Databind or Google Gson library. Java Records are convenient, lightweight and efficient as they automatically generate getters, as well as &lt;em&gt;equals()&lt;/em&gt;, &lt;em&gt;hashCode()&lt;/em&gt;, and &lt;em&gt;toString()&lt;/em&gt; methods.&lt;/p&gt;
&lt;p&gt;In this tutorial, we will be using the Rest-Assured library for executing the API requests and Jackson Databind library with Java Records for serializing the request body used in the API requests.&lt;/p&gt;
&lt;h3 id=&quot;api-under-test&quot;&gt;API under Test&lt;/h3&gt;
&lt;p&gt;We will be using the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/mfaisalkhatri/restful-ecommerce&quot;&gt;restful-ecommerce&lt;/a&gt; APIs in this blog for demonstration. It is free to use E-Commerce Web APIs for practicing API testing and is available over GitHub.&lt;/p&gt;
&lt;p&gt;We will be using the docker-compose file to start the restful-ecommerce application and accordingly execute the API requests on our local machine. &lt;/p&gt;
&lt;h3 id=&quot;test-scenario&quot;&gt;Test Scenario&lt;/h3&gt;
&lt;p&gt;We will use the &lt;em&gt;“/addOrder”&lt;/em&gt; API that will allow adding new orders in the system. The following is the request payload for the  &lt;em&gt;“/addOrder”&lt;/em&gt; API: &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ { 
    &quot;user_id&quot;: &quot;1&quot;,
    &quot;product_id&quot;: &quot;1&quot;,
    &quot;product_name&quot;: &quot;iPhone&quot;,
    &quot;product_amount&quot;: 500.00,
    &quot;qty&quot;: 1,
    &quot;tax_amt&quot;: 5.99,
    &quot;total_amt&quot;: 505.99
}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The request accepts a JSON array with multiple JSON objects that holds the different order details.&lt;/p&gt;
&lt;p&gt;We will serialize the JSON given in the payload using Java Records and execute the POST request to add order in the system verifying that the order is added successfully.&lt;/p&gt;
&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;We would be using the Maven project and adding the following dependencies in the pom.xml file. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.testng&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;testng&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;7.10.2&amp;lt;/version&amp;gt;
 &amp;lt;/dependency&amp;gt;

 &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;io.rest-assured&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;rest-assured&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;5.5.0&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
 &amp;lt;/dependency&amp;gt;

 &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;2.18.1&amp;lt;/version&amp;gt;
 &amp;lt;/dependency&amp;gt;
 &amp;lt;dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The dependencies are for TestNG that acts as a test runner, rest-assured for executing the API requests and Jackson Databind that will help in serialization.&lt;/p&gt;
&lt;p&gt;Let’s create a new package - restful-ecommerce under the &lt;em&gt;src/test&lt;/em&gt; folder in the project. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=8693737744531670164&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let’s add two more packages under the &lt;em&gt;restful-ecommerce&lt;/em&gt; page, the first one with name - &lt;em&gt;pojo&lt;/em&gt; and the second one with name &lt;em&gt;tests&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;test-implementation&quot;&gt;Test Implementation&lt;/h3&gt;
&lt;p&gt;The first step in implementation is to create Java Records with the fields needed for adding the &lt;em&gt;Order&lt;/em&gt; as per the request payload.&lt;/p&gt;
&lt;p&gt;The request payload requires the following fields, hence we will accordingly add those fields to the Record&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;user_id&lt;/li&gt;
&lt;li&gt;product_id&lt;/li&gt;
&lt;li&gt;product_name&lt;/li&gt;
&lt;li&gt;product_amt&lt;/li&gt;
&lt;li&gt;qty&lt;/li&gt;
&lt;li&gt;tax_amt&lt;/li&gt;
&lt;li&gt;total_amt&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The data_type details for these fields can be found on the Swagger using which the fields in the Java Record can be created.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=10651747805031785369&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, let’s add a new Java Record - “Order”, under the &lt;em&gt;pojo&lt;/em&gt; package. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public record Order(String user_id, String product_id, String product_name, int product_amount, int qty, int tax_amt,
                   int total_amt) {
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After adding the Java Record, we can straightaway move to write the API tests and create a new Java class - “AddOrderTests” under the &lt;em&gt;tests&lt;/em&gt; package.&lt;/p&gt;
&lt;p&gt;public class AddOrderTests {&lt;/p&gt;
&lt;p&gt;   @Test&lt;br&gt;
   public void testAddOrder () {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   List&amp;lt;Order&amp;gt; orders = new ArrayList&amp;lt;&amp;gt; ();
   orders.add (new Order (&quot;1&quot;, &quot;34&quot;, &quot;Canon Camera CX12&quot;, 14500, 1, 915, 15415));

   given ().body (orders)
       .when ()
       .log ()
       .all ()
       .contentType (ContentType.JSON)
       .post (&quot;http://localhost:3004/addOrder&quot;)
       .then ()
       .log ()
       .all ()
       .statusCode (201);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;   }&lt;br&gt;
}&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The @Test annotation is from the TestNG library that will allow us to run the tests. The request payload actually accepts JSON Arrays in which multiple objects of Orders are added. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;List&amp;lt;Order&amp;gt; orders = new ArrayList&amp;lt;&amp;gt; ();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first statement in the method is creating a new list that can store Order objects. This will help us in adding multiple order objects to the list and accordingly pass them as the request body. This is done to ensure that we pass the JSON Object under JSON Arrays as the &quot;/addOrder&quot; endpoint needs the request body in JSON Array format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;orders.add (new Order (&quot;1&quot;, &quot;34&quot;, &quot;Canon Camera CX12&quot;, 14500, 1, 915, 15415));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second line in the method adds an object of Order with details. See how simple it is to pass the value to the Records object, Records automatically generates the required constructor for passing the values.&lt;/p&gt;
&lt;p&gt;Next, using rest-assured methods the test for the API is written.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;given ().body (orders)
   .when ()
   .log ()
   .all ()
   .contentType (ContentType.JSON)
   .post (&quot;http://localhost:3004/addOrder&quot;)
   .then ()
   .log ()
   .all ()
   .statusCode (201);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The interpretation of the above code is pretty simple: given a body of order objects, log the request details in the console, the content-type of the request body will be in JSON format. &lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Post&lt;/em&gt; HTTP method should be hit for the API endpoint &lt;em&gt;“&lt;a rel=&quot;nofollow&quot; href=&quot;http://localhost:3004/addOrder”&quot;&gt;http://localhost:3004/addOrder”&lt;/a&gt;&lt;/em&gt;, when the API is executed, then the response details received should be logged in the console and its status code should be checked that should be equal to 201.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test Execution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before we execute the test, we should make sure that the restful-ecommerce application is up and running. We can start the application using the following docker compose command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose -f docker-files/docker-compose-ecommerce.yml up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can then hit the following URL to make sure that the application is up and running. It should display the Swagger docs&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://localhost:3004/api-docs/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9361457111427271547&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, we can run the test and check for the output. The following screenshots show that the JSON is serialized successfully in the API request body.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9545470663108811260&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;addOrder&lt;/em&gt; API is successfully hit and one order is generated.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=15015810893858752380&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Java Records introduced in Java 16 are convenient, lightweight and efficient as they automatically generate getters, as well as equals(), hashCode(), and toString() methods. &lt;/p&gt;
&lt;p&gt;It can be a better fit for JSON serialization and deserialization with Jackson Databind library as it does not require writing a lot of boilerplate code.&lt;/p&gt;
&lt;p&gt;All the code examples shown in this article can be found &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/mfaisalkhatri/api-testing-rest-assured&quot;&gt;over on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy Testing!&lt;/p&gt;
</description>
<category>Java</category>
<guid isPermaLink="true">https://coderlegion.com/477/how-to-serialize-json-api-requests-using-java-records</guid>
<pubDate>Sun, 10 Nov 2024 05:01:58 +0000</pubDate>
</item>
</channel>
</rss>