chubbyphp / chubbyphp-mock
A strict mocking solution.
Installs: 182 484
Dependents: 35
Suggesters: 0
Security: 0
Stars: 4
Watchers: 1
Forks: 1
Open Issues: 0
Requires
- php: ^8.2
- nikic/php-parser: ^5.4
Requires (Dev)
- chubbyphp/chubbyphp-dev-helper: dev-master
- dg/bypass-finals: ^1.9
- infection/infection: ^0.29.12
- php-coveralls/php-coveralls: ^2.7.0
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan: ^2.1.5
- phpunit/phpunit: ^11.5.8
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0.2
- symfony/symfony: ^7.2
README
Description
A strict mocking solution.
Requirements
- php: ^8.2
Installation
Through Composer as chubbyphp/chubbyphp-mock.
composer require chubbyphp/chubbyphp-mock "^2.0" --dev
Usage
<?php declare(strict_types=1); namespace MyProject\Tests\Unit\RequestHandler; use Chubbyphp\Mock\MockMethod\WithCallback; use Chubbyphp\Mock\MockMethod\WithReturn; use Chubbyphp\Mock\MockMethod\WithReturnSelf; use Chubbyphp\Mock\MockObjectBuilder; use MyProject\RequestHandler\PingRequestHandler; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; final class PingRequestHandlerTest extends TestCase { public function testHandle(): void { $builder = new MockObjectBuilder(); $request = $builder->create(ServerRequestInterface::class, []); $responseBody = $builder->create(StreamInterface::class, [ new WithCallback('write', static function (string $string): int { $data = json_decode($string, true); self::assertArrayHasKey('datetime', $data); return \strlen($string); }), ]); $response = $builder->create(ResponseInterface::class, [ new WithReturnSelf('withHeader', ['Content-Type', 'application/json']), new WithReturnSelf('withHeader', ['Cache-Control', 'no-cache, no-store, must-revalidate']), new WithReturnSelf('withHeader', ['Pragma', 'no-cache']), new WithReturnSelf('withHeader', ['Expires', '0']), new WithReturn('getBody', [], $responseBody), ]); $responseFactory = $builder->create(ResponseFactoryInterface::class, [ new WithReturn('createResponse', [200, ''], $response), ]); $requestHandler = new PingRequestHandler($responseFactory); self::assertSame($response, $requestHandler->handle($request)); } }
FAQ
Howto mock final classes/methods
Use the third party package dg/bypass-finals.
This does not work to get rid of the final keyword on internal classes.
What Cannot Be Mocked
-
Static methods
-
Properties
-
__construct, __destruct methods
-
Interfaces extending internal interfaces: Interfaces that extend built-in PHP interfaces like
Traversable
are used as markers rather than containing methods. They cannot be mocked. -
Internal final classes or methods: Even with tools like
dg/bypass-finals
, you cannot mock internal final classes or methods. -
Poorly built extension classes: Some older PHP extensions create classes that cannot be fully reverse-engineered using reflection. These classes are not mockable.
Please report if you find other restrictions / bugs.
Upgrade
Copyright
2025 Dominik Zogg