skip to content

In a Karate mock feature file, what is the text after `Scenario:` used for, and what does the mock return when no `Scenario` matches the incoming request?

level: juniorimportance: must knowfreq 66%

answer

  1. The name is not documentation
  2. Evaluated fresh on every request
  3. Position in the file matters
  4. An empty name always matches
  5. Nothing matched means status 404

basics

~20 s

In a Karate mock feature the Scenario name is a JavaScript expression evaluated per request, not a label. Scenarios are tried in file order; the first one returning true answers, and if none does the mock replies 404.

solid answer

~50 s

In mock mode Karate treats a `Scenario` name as a **JavaScript expression** rather than documentation: it is the request matcher. For each incoming request the handler sets up the request variables and helper functions, then walks the served features in the order they were supplied and, inside each one, the `Scenario` sections from top to bottom, evaluating every name. The **first** expression that evaluates to boolean `true` wins — its steps run, and the response is assembled from the variables they set. Nothing below it is evaluated, so position in the file is the only routing lever; Karate has no priority attribute and does no specificity scoring. A `Scenario:` with an empty name always matches, which makes it the catch-all and is why it belongs last. If no name matches, the handler logs *no scenarios matched, returning 404* and replies **404**.

code

gherkin · 14 lines
gherkin
Feature: cats mock

Background:
* def cats = { '1': { id: 1, name: 'Billie' } }

Scenario: pathMatches('/cats/{id}') && methodIs('get')
* def response = cats[pathParams.id]

Scenario: pathMatches('/cats') && methodIs('get')
* def response = $cats.*

Scenario:
* def response = { error: 'no route' }
* def responseStatus = 404

go deeper

for a junior

Remember the shape: the Scenario name matches the request, the steps below it build the reply. Being able to write a four-scenario mock with a catch-all last is the junior bar.

for a middle

Explain the loop out loud: features in supplied order, scenarios top to bottom, first boolean true wins, nothing after it is evaluated, otherwise 404.

for a senior

Own the failure modes in a shared mock. A broad matcher near the top silently shadows everything below it, and the only evidence is one warning line and a bare 404.

for a principal

Decide whether a team gets one large mock feature or several narrow ones, knowing file order is the only precedence control on offer and no tooling will flag a shadowed stub.

## A name that is code In an ordinary Karate test the words after `Scenario:` are documentation. In a feature served as a mock they are the routing table. The mock handler reads each `Scenario` name as a JavaScript expression and evaluates it against the request that has just arrived. The body of the scenario says what to reply; the **name** says whether to reply at all. That single design choice is why Karate needs no mapping DSL, no matcher builder and no registration API to stand a service up — the file *is* the router. ## The dispatch loop For every incoming request the handler does the same five things: 1. Puts the request in scope as variables — `request`, `requestPath`, `requestUri`, `requestMethod`, `requestHeaders`, `requestParams`, `requestBytes` — and registers the matcher helper functions (`pathMatches`, `methodIs`, `typeContains`, `paramValue`, `bodyPath` and friends). 2. Walks the served features **in the order they were supplied** to the server. 3. Inside each feature, walks the `Scenario` sections **top to bottom**, evaluating each name as JavaScript. 4. Stops at the first name that evaluates to boolean `true`, runs that scenario's steps, and builds the response out of the variables those steps set. 5. Returns immediately — no later scenario, and no later feature, is consulted for that request. Because step 5 returns, matching is genuinely **first-wins and not best-wins**. Two scenarios can both be true for one request and the second will never know it. ## The catch-all A `Scenario:` line with nothing after it produces an empty matcher expression, and the handler special-cases that: an empty expression is treated as *always matches* and the scenario is selected without evaluating anything. That is the idiom for a catch-all, and it is only useful in one place — **last**. Put it first and it swallows every request in the file, which is the single most common way a Karate mock appears "broken". ```gherkin Scenario: pathMatches('/cats/{id}') && methodIs('get') * def response = cats[pathParams.id] Scenario: pathMatches('/cats') && methodIs('post') * def response = { id: 1 } * def responseStatus = 201 Scenario: # nothing matched above - own the failure instead of letting the handler 404 * def response = { error: 'no route', path: '#(requestPath)' } * def responseStatus = 404 ``` ## What happens when nothing matches If every name evaluates to something other than `true`, the handler logs a warning — *no scenarios matched, returning 404* — and replies with status **404**. Two consequences are worth carrying into an interview: - The 404 is the **mock's** 404, not your modelled "resource not found". A test that asserts `status 404` can pass because the mock routed nothing at all. If the service under test is meant to distinguish those cases, give the catch-all a distinctive body so the difference is visible. - Nothing throws. A request that matches no scenario is not an error condition for the mock, so the only trace is that one warning line in the mock's log. ## Ordering is the only lever It is worth being explicit about what Karate deliberately does **not** give you here: - there is no priority or weight on a `Scenario`; - there is no "most specific match" ranking; - there is no separate default-response setting — the empty-name scenario *is* that mechanism; - tags do not participate in mock routing. So the layout rules are simple and mechanical: narrow matchers above broad ones, the broadest above the catch-all, and the catch-all last. A scenario whose name is just `methodIs('post')` sitting at the top of a file will answer every POST to every path, whatever you wrote below it. ## Multiple feature files One mock server can serve several feature files at once. They are evaluated in the order they were supplied, so the same shadowing rule applies one level up: the first feature that contains a matching scenario answers, and swapping the order of two files on the command line or in the builder can change which stub answers. Keep at most one catch-all across the whole set, in the file you intend to be last. ## Why interviewers ask it The question separates people who have only read a mock feature from people who have debugged one. The reading is intuitive — it looks like a list of test cases with descriptive names. The mechanism is not: those names are executed, on every request, in order, and the first `true` ends the search.

  • A Karate mock answers every request from the same scenario. What do you look at first?
    The order of the scenarios and how broad the first one is. Matching stops at the first name that evaluates to `true`, so a scenario named only `methodIs('post')`, or an empty-name catch-all that has drifted to the top of the file, will answer everything below it. Move it down, or narrow it with `pathMatches(...)`.
  • Can one Karate mock server serve more than one feature file, and which one answers?
    Yes — a mock can be started over a list of features. They are evaluated in the order supplied, and the first matching scenario in the first matching feature answers. Re-ordering the files can therefore change the reply, so keep a single catch-all and put it in the file you intend to be last.

It reads like a labelled list of stubs, but it behaves like a firewall rule set: rules are tried top to bottom and the first one that fires ends the search.

saying these in an interview costs you the question

  • Says the Scenario name is just a description
  • Thinks Karate picks the most specific matching scenario
  • Expects an unmatched request to fail with 500
  • Puts the empty-name catch-all at the top of the file
  • Believes every scenario runs for every request
  • Looks for a priority or weight attribute on a scenario