Mocking Interfaces in Tests
Interfaces make unit testing easy — swap real implementations with mocks that return controlled values without side effects.
Interfaces make unit testing easy — swap real implementations with mocks that return controlled values without side effects.
<?php
// PHPUnit example
use PHPUnit\Framework\TestCase;
class OrderServiceTest extends TestCase {
public function test_sends_confirmation_email(): void {
// Create mock for the interface
$mailer = $this->createMock(MailerInterface::class);
// Expect send() to be called once with specific args
$mailer->expects($this->once())
->method("send")
->with("user@example.com", "Order Confirmed", $this->anything())
->willReturn(true);
$service = new OrderService($mailer);
$service->processOrder(["id" => 1, "email" => "user@example.com"]);
// PHPUnit verifies the mock expectations automatically
}
}
Mocking works because PHPUnit generates a class that implements the interface — this only works because of the interface contract.