MicroUnit provides a flexible mocking engine.
Each method is listed below with its signature and a concise explanation.
For an explanation on how to perform assertions on mocks see Assertions.
create(string $class): selfCreates a mock builder for the given class.
$mock = MockBuilder::create(SomeClass::class);
returns(string $method, mixed $value): selfSets a return value for a method.
$mockBuilder->returns('getName', 'John');
returnsSequence(string $method, mixed ...$values): selfSets a sequence of return values for a method. It moves from one return value to the next each time the method is called.
$mockBuilder->returnsSequence('next', 'first', 'second', 'third');
//Call 1: returns 'first'
//Call 2: returns 'second'
//Call 3: returns 'third'
//Call 4 and after: returns null
returnsCallback(string $method, callable $fn): selfSets a callback that is executed when the method gets called.
$mockBuilder->returnsCallback('sum', fn($a, $b) => $a + $b);
throws(string $method, \Throwable $e): selfMakes the method throw the given throwable.
$mockBuilder->throws('fail', new Exception('fail!'));
keepOriginalMethodBehaviour(string $method): selfEnables execution of the original method logic contained inside the class to be mocked.
if no custom return is defined the method will return its original return value. If a custom return is defined the method will return the custom value.
$mock = $mockBuilder->keepOriginalMethodBehaviour('foo');
disableOriginalConstructor(): selfDefines that when creating a mock instance the original constructor of the mocked class should not be called.
$mock = $mockBuilder->disableOrginalConstructor();
executeInConstructor(callable $fn): selfSets a callable that will be executed inside the constructor.
If the original constructor is getting called the callable will be executed after the original constructor was called.
Otherwise it will be executed right away.
$mock = $mockBuilder->executeInConstructor(function (array $constructorArgs) {
echo $constructorArgs[0];
});
withConstructorArgs(array $args): selfSets the arguments that are going to be passed to the constructor and original constructor when an instance of the mocked class is created.
$mock = $mockBuilder->withConstructorArgs([12, 5]);
build(): MicroMockFinalizes and returns the mock object (MicroUnit\Mocking\MicroMock).
$mock = $mockBuilder->build();
See MicroMock section for information on how that obtained mock object can be used.
Note: The
MicroMockclass contains a couple of public properties that are used by theMockBuilderinternally. Altering them onMicroMockdirectly is not recommended and may lead to unexpected behaviour.
newInstance(): objectCreates a new instance of the mocked class.
This instance can be used where an instance of the mocked class is expected.
$instance = $mock->newInstance();
newAlternateInstance(array $constructorArgs): objectCreates an alternate instance of the mocked class using the specified constructor arguments instead of the ones defined during mock building (via $mockBuilder->withConstructorArgs(array $args)).
This instance can be used where an instance of the mocked class is expected.
$instance = $mock->newAlternateInstance(['foo', 17]);
getCallLog(): CallLogReturns the call log for the mock. See CallLog Section for details.
$log = $mock->getCallLog();
A utility class that wraps internal method call data, providing helper methods to access and inspect call details.
Note: For most use cases, it is recommended to validate method calls using the AssertMock class, which uses
Callloginternally to provide assertion methods for mocks.
getCallCount(string $method): intReturns the number of times a method was called.
$count = $log->getCallCount('foo');
getAllCallArgs(string $method): arrayReturns all arguments passed to a method.
$args = $log->getAllCallArgs('foo');
hasCalls(string $method): boolChecks if the given method has any calls.
$args = $log->hasCalls('foo');
getCallSequence(): arrayReturns the full call sequence for all method calls made on the mock.
$sequence = $log->getCallSequence();
echo $sequence;
// Prints something like: ['foo', 'bar', 'foo', 'foo']
use MicroUnit\Mocking\MockBuilder;
use MicroUnit\Assertion\AssertMock;
use Exception;
// In this example we mock a class but you can also mock abstract classes and interfaces of course.
class UserService {
public function __construct(protected string $prefix = '') {}
public function getUserName(int $id): string {
return "Default";
}
public function getNextId(): int {
return 0;
}
public function addUser(string $name): bool {
return true;
}
}
// Build a mock for UserService
$mockBuilder = MockBuilder::create(UserService::class)
->returns('getUserName', 'MockedUser') // fixed return
->returnsSequence('getNextId', 101, 102, 103) // sequence
->returnsCallback('addUser', fn($name) => $name !== '') // dynamic callback
->withConstructorArgs(['USR_']); // mock constructor arg
$mock = $mockBuilder->build();
// Create mock instance (will use constructor args ['USR_'])
$instance = $mock->newInstance();
echo $instance->getUserName(1); // Output: MockedUser
echo $instance->getNextId(); // Output: 101
echo $instance->getNextId(); // Output: 102
var_dump($instance->addUser('John')); // Output: true
var_dump($instance->addUser('')); // Output: false
// Create alternate mock instance with different constructor args
$altInstance = $mock->newAlternateInstance(['ALT_']);
$altInstance->getUserName(42);
// Assertions
AssertMock::begin($mock)
->isCalledTimes('getUserName', 2)
->isCalledAtLeast('getNextId', 2)
->checkMethod('addUser', function ($assert) { // Perform multiple assertions on the same method easily
$assert
->isCalledWith(['Alice']) // check method was called at least once with the argument `Alice`
->isCalledWithOnSpecificCall([''], 2); // check second call had empty string
});