bovigo/callmap
Stub and mock PHP method and function calls via a callmap. Define fixed returns, callbacks, consecutive results, or thrown exceptions, then verify invocations and arguments. Works with any unit test framework; argument checks via bovigo/assert or PHPUnit.
Install bovigo/callmap as a dev dependency with Composer:
composer require --dev bovigo/callmap ^9.0
Ensure PHP 8.3+ and an assertion provider (bovigo/assert or PHPUnit) are available. Begin by importing the main namespaces:
use bovigo\callmap\NewInstance;
use function bovigo\callmap\throws;
use function bovigo\callmap\onConsecutiveCalls;
use function bovigo\callmap\verify;
Start by creating a proxied instance (to exercise real methods unless stubbed) or a pure stub:
$instance = NewInstance::of(MyService::class, $constructorArgs);
// or
$stub = NewInstance::stub(MyService::class);
Then map method return values using returns():
$instance->returns([
'fetchData' => ['id' => 42],
'process' => function($input) { return strtoupper($input); }
]);
Verify interactions:
verify($instance, 'process')->received('hello');
verify($instance, 'fetchData')->wasCalledOnce();
NewInstance::of() when you want real methods to run unless explicitly stubbed, e.g., for partial mocks where only certain dependencies are controlled.NewInstance::stub() for complete isolation—methods not in the callmap return default values (e.g., null, or self for self-returning methods).onConsecutiveCalls() for sequences (e.g., database retries, iterator-like behavior):
$instance->returns(['next' => onConsecutiveCalls('a', 'b', throws(new \EOFError()))]);
'log' => fn(...$args) => error_log(json_encode($args));
verify() returns objects compatible with PHPUnit assertions (extends ExpectationFailedException if PHPUnit available).@return $this or return type is the class/interface itself (non-nullable), calling unmapped methods returns the instance.returns() overwrites the entire callmap on each call—merge mappings if needed or call it once with all stubs.\InvalidArgumentException—great for catching typos (e.g., 'getuser' vs 'getUser').@return docblock support is deprecated and removed in v9.0; rely on native type hints.throws() works with onConsecutiveCalls() for realistic failure sequences (e.g., initial success, then errors), but falls back to default return after exhausting values.bovigo/assert ); omitting it silently disables verification.wrap() only when you intentionally want to return the callable itself, not its result—rare, but useful for factory patterns.-v to see full trace when CallAmountViolation or MissingInvocation is thrown.NewInstance::of() has minimal overhead, but stubbing (stub()) is faster for pure mocks.How can I help you explore Laravel packages today?