PHPUnit Mocks Rules
- Do you use extensive mocking in your PHPUnit tests?
- Do you want to keep your tests clean, maintainable and avoid upgrade hell in the future?
- Do you want to have test that actually test somthing?
This set is for you!
Install
composer require rector/mockstan --dev
Note: Make sure you use phpstan/extension-installer to load necessary service configs.
AvoidAnyExpectsRule
Disallow usage of any() expectation in mocks to ensure that all mock interactions are explicitly defined and verified.
rules: - Rector\Mockstan\Rules\AvoidAnyExpectsRule
$someMock = $this->createMock(Service::class); $someMock->expects($this->any()) ->method('calculate') ->willReturn(10);
❌
$someMock = $this->createMock(Service::class); $someMock->expects($this->once()) ->method('calculate') ->willReturn(10);
👍
ExplicitExpectsMockMethodRule
Require explicit expects() usage when setting up mocks to avoid silent stubs. This is reuired since PHPUnit 12 to avoid silent stubs.
rules: - Rector\Mockstan\Rules\ExplicitExpectsMockMethodRule
$someMock = $this->createMock(Service::class); $someMock->method('calculate')->willReturn(10);
❌
$someMock = $this->createMock(Service::class); $someMock->expects($this->once())->method('calculate')->willReturn(10);
👍
ForbiddenClassToMockRule
Disallow mocking of forbidden/core classes (e.g. \DateTime, Symfony Request or RequestStack, Iterable, Symfony and Doctine event objects etc.).
rules: - Rector\Mockstan\Rules\ForbiddenClassToMockRule
$dateTimeMock = $this->createMock(\DateTime::class);
❌
$dateTime = new \DateTime();
👍
NoDocumentMockingRule
Prevent mocking of Doctrine ODM document classes. Use real instances instead.
rules: - Rector\Mockstan\Rules\NoDocumentMockingRule
$docMock = $this->createMock(App\Document\User::class);
❌
$user = new App\Document\User();
👍
NoDoubleConsecutiveTestMockRule
Avoid creating multiple consecutive methods mocks, one for params and other for return. Use single instead.
rules: - Rector\Mockstan\Rules\NoDoubleConsecutiveTestMockRule
$someMock = $this->createMock(SomeClass::class); $someMock->expects($this->once()) ->method('foo') ->willReturnOnConsecutiveCalls(...) ->willReturnCallback(...)
❌
$someMock = $this->createMock(SomeClass::class); $someMock->expects($this->once()) ->method('foo') // handle params in single call ->willReturnCallback(...)
👍
NoEntityMockingRule
Do not mock Doctrine entity classes. Use real object instance instead.
rules: - Rector\Mockstan\Rules\NoEntityMockingRule
$entityMock = $this->createMock(App\Entity\Product::class);
❌
$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();
❌
$this->someMock = $this->createMock(AnotherService::class); $this->realService = new Service();
👍
NoMockOnlyTestRule
Avoid tests that only create mocks and never assert behavior. Require meaningful assertions with at least once real object to test.
rules: - Rector\Mockstan\Rules\NoMockOnlyTestRule
public function testNothing() { $someMock = $this->createMock(Dependency::class); $someMock->expects($this->once()) ->method('doSomething') ->willReturn(true); $this->assertSame($someMock->doSomething()); }
❌
public function testSomething() { $someMock = $this->createMock(Dependency::class); $realObject = new RealObject($someMock); $this->assertTrue($realObject->doSomething()); }
👍
Happy coding!