exan/moock

Modern class mocking package

Maintainers

Details

github.com/Exanlv/moock

Source

Issues

Installs: 18

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/exan/moock

0.1.10 2026-01-30 18:55 UTC

This package is auto-updated.

Last update: 2026-01-30 18:55:33 UTC


README

Moock logo
A simple way of mocking objects in PHP

Usage

Mocking a class

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Note: This also works for anonymous classes, however as these are not proper class structures, they will not extend the given anonymous class. Rather, they will extend the parent and implement the same interfaces if applicable.

Mocking an interface

use Exan\Moock\Mock;

$userService = Mock::interface(UserServiceInterface::class);

Mocking several interfaces

use Exan\Moock\Mock;

/** @var CreatesUsersInterface&DeletesUsersInterface */
$userService = Mock::interfaces(
    CreatesUsersInterface::class,
    DeletesUsersInterface::class,
);

Replacing a method

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->replace(fn ($email) => $email === '::my_test_email::');

$userService->isValidEmail('::my_test_email::'); // true
$userService->isValidEmail('::other_value::'); // false

Force returning a value

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->forceReturn(true);

$userService->isValidEmail('::my_test_email::'); // true
$userService->isValidEmail('::other_value::'); // true

Force returning a sequence of values

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->forceReturnSequence([true, false]);

$userService->isValidEmail('::my_test_email::'); // true
$userService->isValidEmail('::other_value::'); // false

Force throwing of an exception

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->throwsException(RuntimeException::class);

$userService->isValidEmail('::my_test_email::'); // Fatal error: Uncaught RuntimeException
$userService->isValidEmail('::other_value::'); // ...

Asserting number of calls

use Exan\Moock\Mock;

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->forceReturn(true);

Mock::method($userService->isValidEmail(...))
    ->expect()
    ->not()->toHaveBeenCalled();

$userService->isValidEmail('::my_test_email::');

Mock::method($userService->isValidEmail(...))
    ->expect()->toHaveBeenCalled();

Mock::method($userService->isValidEmail(...))
    ->expect()->toHaveBeenCalledOnce();

$userService->isValidEmail('::my_other_test_email::');

Mock::method($userService->isValidEmail(...))
    ->expect()->toHaveBeenCalledTimes(2);

# Invert any assertion using ->expect()->not()
Mock::method($userService->isValidEmail(...))
    ->expect()->not()->haveBeenCalledTimes(3);

Force returning a sequence of values

use Exan\Moock\Mock;

$realUserService = (...);
$userService = Mock::class(UserService::class);

/**
 * $realUserService does NOT have to implement any of the mocked interfaces or classes
 * it can be anything you want. The only requirement is that method names match.
 */
Mock::partial($userService, $realUserService);

Mock::method($userService->isValidEmail(...))
    ->forceReturn(true);

$userService->isValidEmail('::my_test_email::'); // true
$userService->anyOtherMethod('...'); // calls $realUserService

Expecting specific input

$userService = Mock::class(UserService::class);

Mock::method($userService->isValidEmail(...))
    ->forceReturn(true);

$userService->isValidEmail('::my_test_email::');
$userService->isValidEmail('::my_other_test_email::');
$userService->isValidEmail('::my_other_test_email::');

Mock::method($userService->isValidEmail(...))
    ->expect()
    ->with('::my_test_email::')
    ->toHaveBeenCalledOnce();

Mock::method($userService->isValidEmail(...))
    ->expect()
    ->with('::my_other_test_email::')
    ->toHaveBeenCalledTimes(2);

# Using closures
Mock::method($userService->isValidEmail(...))
    ->expect()
    ->with(fn ($email) => true)
    ->toHaveBeenCalledTimes(3);

$userService->isValidEmail('::my_test_email::', 'test-password');
$userService->isValidEmail('::my_other_test_email::', 'test-password');
$userService->isValidEmail('::my_other_test_email::', 'other-password');

# Using named args
Mock::method($userService->isValidEmail(...))
    ->expect()
    ->with(password: 'test-password')
    ->toHaveBeenCalledTimes(2);