skip to content

How do allOf and anyOf work, and why combine matchers instead of writing several separate assertThat calls?

level: middleimportance: should knowfreq 48%

answer

  1. allOf = AND, anyOf = OR
  2. both(m).and(m) / either(m).or(m) = two-matcher sugar
  3. One value, several conditions → combine
  4. Combined matcher is itself reusable/nestable
  5. Failure message shows the whole combined rule

basics

~20 s

allOf(a, b, c) passes only if all the matchers pass (logical AND); anyOf(a, b, c) passes if at least one passes (logical OR). Combining them lets one assertThat check several conditions on one value and report them together.

solid answer

~40 s

allOf and anyOf are *combinator* matchers: they take other matchers and join them. allOf(m1, m2, ...) is a logical AND — the value must satisfy every sub-matcher; anyOf(...) is a logical OR — at least one. For example assertThat(age, allOf(greaterThan(18), lessThan(65))). The benefit over multiple assertThat lines is a single, richly-described expectation: the failure message shows the whole combined condition and which part failed ('Expected: (a value greater than <18> and a value less than <65>) but: was <70>'), and the assertion reads as one logical statement about the value. allOf short-circuits its description to point at the failing clause. Use them when several conditions describe the *same* value; for conditions on *different* values, separate assertions are clearer. There is also both(m).and(m) / either(m).or(m) sugar for the two-matcher case.

go deeper

for a junior

Knows allOf is AND and anyOf is OR and can read a combined assertion.

for a middle

Combines matchers on one value, uses both/either sugar, and explains the better failure message.

for a senior

Decides between combinators and separate assertions, names/reuses combined matchers, and nests them in collection matchers.

for a principal

Sets conventions for when to combine vs split assertions and how combinators interact with soft/grouped-assertion strategies team-wide.

## Combinators: matchers that take matchers Most matchers inspect a value. A **combinator** instead takes *other matchers* and produces a new matcher whose result is a logical combination of theirs. Hamcrest's two main combinators are: - **`allOf(m1, m2, …)`** — logical **AND**. The value must satisfy *every* sub-matcher. Fails as soon as one fails. - **`anyOf(m1, m2, …)`** — logical **OR**. The value must satisfy *at least one* sub-matcher. ``` assertThat(age, allOf(greaterThan(18), lessThan(65))); assertThat(status, anyOf(equalTo("OPEN"), equalTo("PENDING"))); ``` There is two-matcher sugar that reads even better: ``` assertThat(age, both(greaterThan(18)).and(lessThan(65))); assertThat(status, either(is("OPEN")).or(is("PENDING"))); ``` ## Why not just write several assertThat lines? You *can* write: ``` assertThat(age, greaterThan(18)); assertThat(age, lessThan(65)); ``` That is fine and sometimes clearer. But combining has real advantages when the conditions describe **one** value: 1. **Single self-describing expectation.** The failure message states the whole combined rule: `Expected: (a value greater than <18> and a value less than <65>) but: was <70>`. You see the full intent, not just the one line that happened to run first. 2. **It reads as one logical statement** about the value — closer to the spec ('age is an adult under 65'). 3. **Reusable as a value.** Because the combination is itself a matcher object, you can name it and reuse it: `Matcher<Integer> workingAge = allOf(greaterThan(18), lessThan(65));`. 4. **Nests anywhere a matcher is accepted**, e.g. `hasItem(allOf(...))`. ## Short-circuiting & description `allOf` stops at the first failing sub-matcher (AND short-circuit). The mismatch description points at the clause that failed, so you are not left guessing. `anyOf` only fails if *all* sub-matchers fail, and then describes the OR of all of them. ## When to prefer separate assertions If the conditions are about **different** values (`assertThat(name, ...); assertThat(age, ...)`) keep them separate — combining unrelated checks hurts readability and the message. Also, with **separate** assertions the first failure stops the test, so you may not learn the second also failed; tools like assertAll (JUnit 5) or AssertJ soft assertions address that differently. Combinators are about *one value, several conditions reported together*. ## Terms - *Combinator*: a function/object that combines other objects of the same kind into a new one. - *Short-circuit*: stop evaluating once the result is determined (AND stops at first false). - *Logical AND/OR*: true-when-all / true-when-any. ## Gotcha `allOf`/`anyOf` are about combining matchers on **one** value, not about checking multiple independent values; don't cram unrelated checks into one.

  • What does both(greaterThan(0)).and(lessThan(100)) translate to?
    It is sugar for allOf(greaterThan(0), lessThan(100)) — a logical AND of the two matchers on the same value.
  • When are two separate assertThat lines preferable to allOf?
    When the conditions describe different values, or when you intentionally want each as a distinct, independently-named assertion; combine only conditions on the same value.

saying these in an interview costs you the question

  • Swapping the meaning: allOf is AND, not OR
  • Using combinators to check several unrelated values in one assert
  • Thinking anyOf fails if one sub-matcher fails (it fails only if all fail)
  • Assuming combinators change short-circuit/early-exit of the surrounding test

context