A Karate scenario reads `Given url 'https://api.example.com'`, `And path 'cats'`, `And request { name: 'Billie' }`, `When method post`, `Then status 201`. Which of those steps actually puts a request on the wire, and what does the `status` step do?
answer
- Only one step opens a socket
- The rest just accumulate state
- Look for the verb keyword
- method fires, status asserts afterwards
basics
~20 sThe method step sends it. The url, path and request steps only accumulate state on Karate's request builder; method is what fires the call. The status step then asserts the response code and fails if it is anything else.
solid answer
~50 sKarate assembles one HTTP request out of separate steps. `url`, `path`, `param`, `header`, `cookie`, `request`, `form field` and `multipart field` each write into a per-scenario request builder and send nothing at all. **`method <verb>` is the trigger** — it records the verb and immediately invokes the HTTP client, so a scenario that never reaches a `method` step never makes a call. The verb is matched case-insensitively, and `method verb` evaluates a variable that holds it. `soap action` is the one other keyword that fires a call itself: it sets `SOAPAction`, forces `text/xml` and performs the POST. Once a response is back Karate auto-binds `response`, `responseStatus`, `responseHeaders` and `responseTime`, and `status 201` is a shortcut assertion on the status. It parses a literal number, so an expected code held in a variable needs `match responseStatus == expected` instead.
code
gherkin · 9 linesScenario: create a cat
Given url 'https://api.example.com'
And path 'cats'
And header Accept = 'application/json'
And request { name: 'Billie', type: 'LOL' }
When method post
Then status 201
And match response.name == 'Billie'
And match responseStatus == 201go deeper
Remember the shape: everything above the method step is setup, the method step sends, and status plus match check what came back.
Be able to explain that a single per-scenario request builder holds the state and that method both sets the verb and invokes the client synchronously.
In review, count the method and soap action steps to count the real HTTP calls; that catches scenarios that fire twice or never fire at all.
The tradeoff worth naming is that a keyword-is-the-implementation model removes the glue layer but also removes the seam where teams used to put cross-cutting request policy.
## The scenario is one request, spelled out in steps A Karate `Scenario` does not build a request object that you then hand to a client. Each built-in HTTP keyword writes into a request builder that lives for the duration of the scenario, and that builder holds the state until something fires it. | Keyword | What it writes | Sends anything? | |---|---|---| | `url` | the base URL | no | | `path` | one or more path segments, appended | no | | `param` / `params` | query-string entries | no | | `header` / `headers` | request headers | no | | `cookie` / `cookies` | request cookies | no | | `request` | the request body | no | | `form field` / `multipart field` / `multipart file` | a form body | no | | `method` | the verb — **and invokes the client** | **yes** | | `soap action` | `SOAPAction` + `text/xml` — **and posts** | **yes** | | `status` | nothing; asserts the response code | no | There is no step-definition class behind any of these. The keyword *is* the implementation, which is why a Karate project has no glue package to write, register or point a runner at. ## What `method` actually does The `method` step does two things in order: it records the verb on the builder, then it invokes the HTTP client right there, synchronously, before the next step runs. 1. The text after `method` is upper-cased and checked against the nine standard verbs — GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, CONNECT, TRACE — so `method get`, `method GET` and `method Get` are the same step. 2. If it is not one of those, Karate evaluates the text as an expression, which is how `method verb` works when `verb` holds `'post'`. 3. If the request has no URL at all, the call fails before it leaves the process with a complaint that the request is incomplete. 4. If the scenario never reaches a `method` step, nothing is sent and `response` is never bound — a `match response ...` afterwards fails on an undefined variable, not on a bad payload. That last point is the practical consequence of the design: a scenario that assembles a perfect request and forgets the `method` step is not a failing HTTP test, it is a test that made no HTTP call. ## `status` is an assertion, not a label `status 201` compares the response status to that number and fails the step when they differ. Two details matter: - **The number must be a literal.** The step parses the text after `status` as an integer, so `status expectedCode` fails on the step itself — it never reaches a comparison. - **It only handles one exact code.** For a variable, a range, or a set of acceptable codes, drop the shortcut and assert on the auto-bound variable: `match responseStatus == expected`, or `match [200, 201] contains responseStatus`. ## The keyword that fires without saying `method` `soap action` is easy to misread as a header-setting step. It sets the `SOAPAction` header, forces the content type to `text/xml`, **and then performs the POST itself**. Writing `When method post` after it does not "complete" the call; it sends a second one, this time with the SOAPAction header and body already cleared. ```gherkin Scenario: soap action fires the call by itself Given url 'https://api.example.com/services/balance' And request read('query-balance.xml') When soap action 'QueryUsageBalance' Then status 200 And match /Envelope/Body/Result/Code == 'OK' ``` ## What is bound once the response is back Every call rebinds four variables, and they are what the rest of the scenario asserts on: - `response` — the body, already converted to a map, a list, an XML node, a string or bytes according to its content type. - `responseStatus` — the status code as a number. - `responseHeaders` — a map of header name to a list of values. - `responseTime` — elapsed milliseconds for that call. Because they are rebound on every call, they always describe the **most recent** request in the scenario. If you need a value from an earlier call, capture it with `def` before you fire the next one. ## Reading a scenario back The useful habit is to scan a Karate scenario for its `method` and `soap action` steps first: that tells you how many HTTP calls it makes. Everything above a `method` step is setup for that one call, and everything below it up to the next `method` step is assertion on that one response.
- Is `method` the only keyword in a Karate feature file that sends a request?No. `soap action` fires one too: it sets the `SOAPAction` header, sets `Content-Type: text/xml`, and performs a POST itself. That is why you never write `method post` after it — doing so sends a second, emptied request. Every other HTTP keyword only writes into the request builder.
- How do you assert a status code that is not a fixed literal?Use the auto-bound `responseStatus` variable with `match`. `status` parses the text after it as an integer, so `status expectedCode` fails on the step itself. Write `match responseStatus == expectedCode`, or for a set of acceptable codes, `match [200, 201, 202] contains responseStatus`.
- What happens if a scenario sets `path` and `request` but no `method` step?No HTTP call is made. The builder simply keeps that state, and `response`, `responseStatus`, `responseHeaders` and `responseTime` are never bound, so the first assertion that touches `response` fails on an undefined variable rather than on a payload mismatch.
saying these in an interview costs you the question
- Says the url step is what sends the request
- Thinks each HTTP keyword makes its own call
- Expects a step-definition class behind method
- Writes method post after soap action, firing twice
- Writes status expectedCode with a variable name
- Treats Then status 200 as documentation, not an assertion