rector/mockstan

Static analysis for PHPUnit mocks

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

Type:phpstan-extension

pkg:composer/rector/mockstan

dev-main 2026-02-08 10:20 UTC

This package is auto-updated.

Last update: 2026-02-08 10:21:00 UTC


README

Downloads

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!