Skip to content

Arg ​

Rasuvaeff\Understudy\Arg

Class — Package: rasuvaeff/understudy — Source — Version: v1.1.0-1-g6ed023f

Argument matchers, usable only inside a specification closure:

php
when(fn () => $repository->find(Arg::any()))->returns($book);

Every matcher is declared to return mixed rather than the internal ArgumentMatcher type. That is not vagueness — it is what the matcher means. A matcher stands in for a value of whatever type the parameter declares, and it is never consumed as a value: the runtime intercepts it while recording the call specification. Declaring the concrete class instead would make find(Arg::any()) a type error in every IDE and analyser for a contract that says find(int $id), on the first line of the first example anyone copies — while mixed is accepted everywhere and stays honest.

understudy-psalm narrows this to the parameter's declared type, so users of the plugin get a real check rather than mixed.

Methods ​

any() ​

php
static any(): mixed

Matches any argument, including null.

int() ​

php
static int(?int $min = NULL, ?int $max = NULL): mixed

Matches an int, optionally within bounds. A numeric string does not match: the matcher pins the declared type as well as the value.

float() ​

php
static float(?float $min = NULL, ?float $max = NULL): mixed

Matches a float, optionally within bounds. An int does not match.

string() ​

php
static string(non-empty-string|null $matches = NULL): mixed

Matches a string, optionally against a PCRE pattern.

  • $matches — delimiters included, e.g. /^ord-/

bool() ​

php
static bool(): mixed

Matches a bool, either value.

same() ​

php
static same(mixed $value): mixed

Strict identity — for objects, the very same instance.

not() ​

php
static not(mixed $value): mixed

Negates a literal or another matcher: not(5), not(Arg::instanceOf(…)).

allOf() ​

php
static allOf(mixed $operands): mixed

Matches an argument every operand accepts. An operand is a matcher or a literal, the same pair not() takes.

  • $operands — at least one; a tail matcher is not one of them

anyOf() ​

php
static anyOf(mixed $operands): mixed

Matches an argument at least one operand accepts. With literals it reads as a set: anyOf('draft', 'review').

  • $operands — at least one; a tail matcher is not one of them

instanceOf() ​

php
static instanceOf(class-string $type): mixed

Matches an object by its class or interface.

captor() ​

php
static captor(class-string<\T>|null $class = NULL): Captor

A typed argument captor. Its capture() goes where the argument to observe goes, matches like instanceOf() — or like any() for the untyped form — and records the value once the whole specification matched:

php
$options = Arg::captor(DeliveryOptions::class);
when(fn () => $store->temporaryUrl(Arg::any(), Arg::any(), $options->capture()))
    ->returns('https://…');

$subject->run();

$options->last();   // DeliveryOptions, typed
$options->all();    // list<DeliveryOptions>, in call order

The typed replacement for reading args[N] out of the call log: last() and all() carry the class through, so no instanceof narrowing ritual is needed at the read site.

satisfies() ​

php
static satisfies(
    callable $predicate,
    non-empty-string $description = 'satisfies(…)',
): mixed

Matches whatever the predicate accepts.

  • $description — shown in failure messages

A predicate that throws is not caught, and that is the decision rather than an omission. Arg::which() swallows a throwing getter because the getter belongs to the argument — foreign code, reached while the subject is running, where "it threw" can only mean "not this one". A predicate is the test's own code: an exception in it is a broken test, and turning that into a quiet mismatch would report the symptom (an expectation never met) instead of the cause.

containing() ​

php
static containing(array<array-key,mixed> $entries): mixed

Matches an array containing these entries and possibly more: a list by value, a map by key and value.

count() ​

php
static count(int<0, max>|null $minimum = NULL, int<0, max>|null $maximum = NULL): mixed

Matches an array or Countable whose size is within bounds.

which() ​

php
static which(non-empty-string $method, mixed $value): mixed

Matches an object whose getter answers this value.

  • $method — public, non-static, no required arguments

none() ​

php
static none(): mixed

Requires the variadic tail to be empty. Only valid as the last argument.

remaining() ​

php
static remaining(): mixed

Matches the whole variadic tail, of any length including none. Only valid as the last argument.

rest() ​

php
static rest(): mixed

"The arguments before this one matter, the rest of the arity does not." Only valid as the last argument, and the one matcher that lets a specification stop before the method's required parameters run out:

php
when(fn () => $storage->recordOutcome('svc', Arg::rest()))
    ->throws(new RuntimeException('storage unavailable'));

The distinction from remaining(): remaining() stands for the variadic tail a method declares; rest() stands for declared parameters the specification chose not to spell out. A later, narrower specification for the same call still wins over the broad prefix stub, the way overlapping matchers already compose.