rector / mockstan
Static analysis for PHPUnit mocks
Fund package maintenance!
tomasvotruba
www.paypal.me/rectorphp
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:phpstan-extension
pkg:composer/rector/mockstan
Requires
- php: >=8.3
- phpstan/phpstan: ^2.1.38
Requires (Dev)
- nikic/php-parser: ^5.7
- phpstan/extension-installer: ^1.4
- phpunit/phpunit: ^11.5
- rector/jack: ^0.5
- rector/rector: ^2.3.6
- shipmonk/composer-dependency-analyser: ^1.8
- symplify/easy-coding-standard: ^13.0.4
- symplify/phpstan-extensions: ^12.0
- tomasvotruba/class-leak: ^2.1
- tomasvotruba/type-coverage: ^2.1
- tomasvotruba/unused-public: ^2.2
- tracy/tracy: ^2.11
This package is auto-updated.
Last update: 2026-02-08 10:21:00 UTC
README
Set of x+ PHPStan fun and practical rules that check:
@todo
Useful for any type of PHP project, from legacy to modern stack.
Install
composer require rector/mockstan --dev
Note: Make sure you use phpstan/extension-installer to load necessary service configs.
### ExplicitExpectsMockMethodRule Require explicit `expects()` usage when setting up mocks to avoid silent stubs. ```yaml rules: - Rector\Mockstan\Rules\ExplicitExpectsMockMethodRule
// Bad (implicit stubbing) $mock = $this->createMock(Service::class); $mock->method('calculate')->willReturn(10);
❌
// Good (explicit expects) $mock = $this->createMock(Service::class); $mock->expects($this->any())->method('calculate')->willReturn(10);
ForbiddenClassToMockRule
Disallow mocking of forbidden/core classes (e.g. \DateTime, framework internals).
rules: - Rector\Mockstan\Rules\ForbiddenClassToMockRule
// Bad $dtMock = $this->createMock(\DateTime::class);
❌
// Good $dt = new \DateTime();
NoDocumentMockingRule
Prevent mocking of document classes (persisted models) — use real instances or factories.
rules: - Rector\Mockstan\Rules\NoDocumentMockingRule
// Bad $docMock = $this->createMock(App\Document\User::class);
❌
// Good $user = new App\Document\User();
NoDoubleConsecutiveTestMockRule
Avoid creating multiple consecutive mocks in test body that indicate poor test design.
rules: - Rector\Mockstan\Rules\NoDoubleConsecutiveTestMockRule
// Bad $a = $this->createMock(A::class); $b = $this->createMock(B::class);
❌
// Good — combine setup or use single test-specific fixture $a = $this->createMock(A::class); // configure $a as needed, or refactor test
NoEntityMockingRule
Do not mock entity classes (Doctrine entities); use real entity instances.
rules: - Rector\Mockstan\Rules\NoEntityMockingRule
// Bad $entityMock = $this->createMock(App\Entity\Product::class);
❌
// Good $product = new App\Entity\Product();
NoMockObjectAndRealObjectPropertyRule
Disallow assigning a mock to a property while another test uses the real object on the same property.
rules: - Rector\Mockstan\Rules\NoMockObjectAndRealObjectPropertyRule
$this->service = $this->createMock(Service::class); $this->service = new Service();
❌
// Good — keep property consistent or isolate tests $this->service = $this->createMock(Service::class); // or $this->service = new Service();
👍
NoMockOnlyTestRule
Detect tests that only create mocks and never assert behavior — require meaningful assertions.
rules: - Rector\Mockstan\Rules\NoMockOnlyTestRule
// Bad public function testSomething() { $this->createMock(Dependency::class); }
❌
public function testSomething() { $dep = $this->createMock(Dependency::class); $this->assertInstanceOf(Dependency::class, $dep); }
👍
ParamNameToTypeConventionRule
Interface must be located in "Contract" or "Contracts" namespace
rules: - Rector\Mockstan\Rules\CheckRequiredInterfaceInContractNamespaceRule
namespace App\Repository; interface ProductRepositoryInterface { }
❌
namespace App\Contract\Repository; interface ProductRepositoryInterface { }
👍
Happy coding!