Skip to content

Capturing arguments

Arg::captor() is the typed replacement for reading args[N] out of the call log: no positional index, no mixed, no instanceof narrowing ritual.

php
$options = Arg::captor(DeliveryOptions::class);      // Captor<DeliveryOptions>

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

$subject->run();

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

capture() goes where the argument to observe goes.

How it matches

FormMatches like
Arg::captor(SomeClass::class)Arg::instanceOf(SomeClass::class)
Arg::captor()Arg::any()

The value is recorded only once the whole specification matched the call. A call that the other arguments rejected captures nothing — the captor holds what the specification claimed, not everything that went past it.

Where it works

In when(), expect() and verify() alike. A verify() captures from the calls it just claimed, which is the Mockito reading.

Not inside a protocol step

A capture() inside an expectSequence() step matches but does not record. Capture at declaration or at verification, not in a protocol.

Reading it

CallOn an empty captor
last()raises NothingCaptured
all()answers an empty list

The asymmetry is deliberate: last() is asked when the test believes a call happened, so silence there would be a false green; all() is asked to iterate, where an empty list is a perfectly ordinary answer.

Lifetime

Captured values live exactly as long as the call log. reset() and a closing Understudy::scope() drop them, and the captor object is then simply empty again.