Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mokket

A PHPUnit extension that auto-injects mock objects into test properties via a PHP attribute, and provides a typed helper for configuring them.

Requirements

  • PHP 8.2+
  • PHPUnit 12.5+

Installation

composer require --dev ariverrun/mokket

Setup

Register the extension in your phpunit.xml:

<phpunit bootstrap="vendor/autoload.php">
    <extensions>
        <bootstrap class="Ariverrun\Mokket\Extension\MokketExtension"/>
    </extensions>
</phpunit>

Usage

#[Mocked] — auto-inject mocks

Add the #[Mocked] attribute to any typed property in your test class. Before each test method runs, the extension will call createMock() on the property's declared type and inject the result.

use Ariverrun\Mokket\Attribute\Mocked;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\TestCase;

#[AllowMockObjectsWithoutExpectations]
final class OrderServiceTest extends TestCase
{
    #[Mocked]
    private PaymentGatewayInterface $gateway;

    #[Mocked]
    private InventoryRepository $inventory;

    public function testPlaceOrder(): void
    {
        $this->gateway->method('charge')->willReturn(true);

        $service = new OrderService($this->gateway, $this->inventory);
        $this->assertTrue($service->placeOrder($order));
    }
}

Every test method receives a fresh mock — state and configuration from a previous test never carry over.

mockof() — typed mock access

mockof() accepts any object and returns it as a MockObject. If the argument is already a MockObject, the same instance is returned. Otherwise, a new mock wrapping the object's class is created.

The function is generic, so static analysis tools and IDEs will infer the full type of the returned mock.

use function Ariverrun\Mokket\Util\mockof;

Configuring return values:

mockof($this->gateway)
    ->method('charge')
    ->willReturn(true);

Configuring expectations:

mockof($this->gateway)
    ->expects($this->once())
    ->method('charge')
    ->willReturn(true);

Wrapping a concrete object:

$logger = new FileLogger('/tmp/test.log');
$mock = mockof($logger); // MockObject&FileLogger — original methods are NOT called

Behaviour reference

Scenario Result
#[Mocked] on an interface or class property Property is set to a fresh MockObject before each test
#[Mocked] on a built-in type (string, int, …) Property is skipped — built-in types cannot be mocked
#[Mocked] on an untyped property Property is skipped
Property without #[Mocked] Not touched — PHP leaves it uninitialized
mockof(MockObject) Returns the same object
mockof(object) Returns a new MockObject of the same class; original methods are NOT called

PHPUnit notice about mock objects without expectations

PHPUnit 12 emits a notice when a MockObject is created but no expects() call is made on it. If you use #[Mocked] properties only for stubbing (setting return values with willReturn(), not verifying call counts), suppress the notice with the #[AllowMockObjectsWithoutExpectations] attribute:

use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;

#[AllowMockObjectsWithoutExpectations] // on the class
final class MyTest extends TestCase { ... }
#[AllowMockObjectsWithoutExpectations] // or on a single method
public function testSomething(): void { ... }

API

Ariverrun\Mokket\Attribute\Mocked

#[Attribute(Attribute::TARGET_PROPERTY)]
final readonly class Mocked {}

Marks a test class property for automatic mock injection. The property must have a non-built-in type declaration.

Ariverrun\Mokket\Util\mockof()

/**
 * @template T of object
 * @param T $object
 * @return T&MockObject
 */
function mockof(object $object): MockObject

Returns a MockObject typed as the original class or interface, enabling IDE autocompletion and static analysis for both mock configuration methods and the original API.

Ariverrun\Mokket\Extension\MokketExtension

The PHPUnit extension entry point. Register it in phpunit.xml to activate #[Mocked] injection. Accepts no parameters.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages