exan / moock
Modern class mocking package
Installs: 18
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/exan/moock
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.92
- phpunit/phpunit: ^11.5
- symfony/var-dumper: ^7.4
README

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);