In a Karate feature file, `* match each items == { active: true }` runs when `items` is an empty array. Does the step pass or fail, and how do you change that?
answer
- one expectation, applied to every element
- the pathological case is the empty list
- vacuous truth is refused on purpose
- a configure step flips the guard
- the default is the safe one
basics
~10 sThe step fails. Karate's match each rejects an empty array by default and reports 'match each failed, empty array / list'. Adding the step configure matchEachEmptyAllowed = true makes an empty list pass vacuously.
solid answer
~40 s`match each` applies one expected shape to every element of a list. Before it iterates, it checks two things: the left side must actually be a list (otherwise the failure is `actual is not an array or list`), and the list must not be empty. An empty list fails with `match each failed, empty array / list` — the default is deliberately **not** vacuous truth, because a filter or query that returned zero rows would otherwise make every per-element assertion pass silently and the suite would go green while the endpoint returned nothing. When an empty collection is a legitimate outcome for the case under test, `* configure matchEachEmptyAllowed = true` flips the guard off; the setting can also be applied suite-wide from `karate-config.js` via `karate.configure('matchEachEmptyAllowed', true)`.
code
gherkin · 10 linesFeature: match each and empty arrays
Scenario: opting in to a vacuous pass
* configure matchEachEmptyAllowed = true
* def items = []
* match each items == { active: true }
Scenario: with elements present, every one must match
* def items = [{ active: true }, { active: true }]
* match each items == { active: true }go deeper
Remember that a match each over an empty list fails rather than passing, and that the message names the emptiness explicitly rather than pointing at any element.
Explain why the default is a refusal: vacuous truth would let a query returning zero rows turn every per-element assertion green while the endpoint was broken.
Treat a scenario that needs the flag as a signal to check the assertion's intent — an empty result is usually worth asserting directly rather than shaped with a per-element expectation.
Set the standard for where suite-wide leniency may live at all. A safety net removed once in a shared config file is invisible to every author who inherits it afterwards.
## What `match each` does `match each` is the per-element form of Karate's comparison. Instead of comparing the left operand to the right operand as a whole, it takes the right operand as an expectation and applies it to **every** element of the list on the left. `* match each items == { active: true }` asserts that each element of `items` is an object equal to `{ active: true }` — one step standing in for a loop. Two preconditions are checked before any element is looked at: 1. **The left side must be a list.** If it is a map, a string or a number, the step fails with `actual is not an array or list`. There is no implicit wrapping. 2. **The list must not be empty** — unless you have said otherwise. ## The empty-list guard, and why it is on by default An empty list is the pathological case for any per-element assertion. Read as pure logic, "every element of the empty set satisfies P" is true, and a naive implementation would pass. Karate refuses instead, failing with `match each failed, empty array / list`. The reason is that this is where per-element assertions do their worst work. Consider a search endpoint asserted with `match each results == { status: 'ACTIVE' }`. If a query regression makes the endpoint return `[]`, vacuous truth would let the step pass — and the suite would report green while the feature was completely broken. The guard turns the most dangerous silent pass in the whole comparison surface into a loud, named failure. ## Turning the guard off, on purpose Some cases genuinely expect nothing back: a filter that should exclude everything, a tenant with no records yet, a deleted-then-listed resource. For those, Karate exposes a switch: - **Per scenario**, as a step: `* configure matchEachEmptyAllowed = true`. Configuration set this way applies from that point in the scenario onward. - **Suite-wide**, from `karate-config.js`: `karate.configure('matchEachEmptyAllowed', true)`. The default is `false`. Note what the flag does *not* do: it does not make an empty list match anything special, and it does not affect `==` on a list — two empty arrays already compare equal under plain `==` without any configuration. It only removes the emptiness precondition from the `each` form. ## Scope it as narrowly as the case Setting the flag globally in `karate-config.js` is the tempting move and usually the wrong one. It is a suite-wide removal of a safety net, applied to buy one scenario's convenience, and it silently weakens every other `match each` in the run. The narrow forms are better: - Set `configure matchEachEmptyAllowed = true` inside the one scenario that expects an empty collection. - Or drop `each` entirely for that case and assert the emptiness directly, which is more honest about the intent: an empty result is a fact worth asserting on its own, not a shape worth applying an element expectation to. ## When elements are present With a non-empty list, the expectation is applied to each element in turn and the failure names the position. A single failing element reports `match each failed at index 3`, and the nested lines under it name the exact path inside that element and print both values — the same path-named trail a plain `==` produces, rooted at the element that broke rather than at the whole list. The element currently under test is also bound to a variable, `_$`, for the duration of its comparison, so an expectation may refer to sibling fields of the same element. That makes `match each` more than a loop: it can express a per-element invariant, not only a per-element literal. ## The shape of the assertion, summarised | situation | result under `match each ... ==` | |---|---| | left side is not a list | fails: `actual is not an array or list` | | list is empty, flag not set | fails: `match each failed, empty array / list` | | list is empty, flag set to true | passes | | every element matches | passes | | one element differs | fails, naming the index and the path inside it | The default is the interesting one. Every other row is what you would guess; the empty-list refusal is the design decision, and it is the one an interviewer is actually asking about.
- In Karate, what happens if the left operand of `match each` is a JSON object rather than an array?The step fails with `actual is not an array or list`. There is no implicit wrapping of a single value into a one-element list, so `match each` is only ever a per-element assertion over a real list. Pointing it at a map is treated as an authoring mistake, not as a one-element case.
- Should `matchEachEmptyAllowed` be set globally in karate-config.js?Rarely. Setting it there removes the empty-list safety net from every `match each` in the suite in order to accommodate one scenario, which is exactly the trade the default was chosen to prevent. Set it as a `configure` step inside the scenario that legitimately expects an empty collection, or assert the emptiness directly instead.
saying these in an interview costs you the question
- Says an empty array passes because every element vacuously matches
- Thinks the flag defaults to true
- Confuses the guard with plain == on two empty arrays
- Sets the flag globally to silence one failing scenario
- Expects match each to wrap a single object into a list
- Claims match each reports nothing about which element failed