PHP - Mocking and Stubbing in PHP Tests

Mocking and stubbing are essential techniques used in unit testing to isolate the code being tested. They allow developers to simulate the behavior of dependencies so that tests focus only on the logic of the unit under test, without relying on external systems such as databases, APIs, or file systems.


Understanding the Need for Mocking and Stubbing

In real-world applications, classes often depend on other classes or services. These dependencies may:

  • Perform slow operations (database queries, API calls)

  • Produce unpredictable results

  • Be difficult to set up in a test environment

To ensure reliable and fast tests, these dependencies are replaced with controlled test doubles such as mocks and stubs.


What is Stubbing

A stub is a simplified implementation of a dependency that returns predefined data. It does not contain real logic and is used only to provide consistent inputs to the test.

Example of Stubbing

class UserRepositoryStub {
    public function getUserById($id) {
        return ['id' => $id, 'name' => 'Test User'];
    }
}

In this case, instead of querying a real database, the stub returns fixed data. This ensures that the test behaves consistently every time.


Purpose of Stubs

Stubs are used when:

  • You need predictable input data

  • The real dependency is slow or unavailable

  • You want to isolate the unit being tested

They do not verify how they are used; they only provide data.


What is Mocking

A mock is a more advanced test double that not only simulates behavior but also verifies interactions. It checks whether certain methods were called, how many times they were called, and with what arguments.

Example of Mocking Concept

Instead of just returning data, a mock ensures that a method is invoked correctly:

  • Was a specific method called?

  • How many times was it called?

  • Were the correct parameters passed?


Example Using PHPUnit Mock

use PHPUnit\Framework\TestCase;

class UserServiceTest extends TestCase {
    public function testSendWelcomeEmail() {
        $mailer = $this->createMock(Mailer::class);

        $mailer->expects($this->once())
               ->method('send')
               ->with($this->equalTo('[email protected]'));

        $service = new UserService($mailer);
        $service->sendWelcomeEmail('[email protected]');
    }
}

Here, the mock verifies that the send method is called exactly once with the correct email.


Key Differences Between Mocking and Stubbing

  • Stubs provide predefined data without verifying interactions

  • Mocks both simulate behavior and verify method calls

  • Stubs focus on inputs, mocks focus on behavior


Types of Test Doubles

Mocking and stubbing fall under a broader category called test doubles. These include:

  • Dummy: Placeholder object with no behavior

  • Stub: Returns fixed data

  • Mock: Verifies interactions

  • Spy: Records information about method calls

  • Fake: Has a simplified but functional implementation


Benefits of Mocking and Stubbing

These techniques improve testing in several ways:

  • Enable isolation of the unit under test

  • Make tests faster by avoiding real dependencies

  • Provide predictable and repeatable results

  • Allow testing of edge cases and error conditions

  • Improve confidence in code correctness


Best Practices

  • Use stubs when you only need to control returned data

  • Use mocks when you need to verify behavior or interactions

  • Avoid overusing mocks, as it can make tests fragile

  • Keep tests simple and focused on one behavior

  • Mock external systems, not internal logic


Common Tools in PHP

Several tools support mocking and stubbing:

  • PHPUnit (built-in mocking framework)

  • Mockery (a popular mocking library)

  • Prophecy (used in older PHPUnit versions)


Challenges

  • Over-mocking can lead to tests that depend too much on implementation details

  • Poorly designed mocks can make tests hard to maintain

  • Misuse can reduce test reliability instead of improving it


Conclusion

Mocking and stubbing are powerful techniques in PHP testing that help isolate code and ensure reliable unit tests. Stubs provide controlled data, while mocks verify interactions between components. When used correctly, they make testing faster, more predictable, and more effective, contributing to higher-quality software and better maintainability.