How to pass arguments to a mocked class constructor

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

How to Pass Arguments to a Mocked Class Constructor: Mastering Dependency Setup

As developers, mocking is an essential tool for isolating units of code and testing complex interactions. However, when dealing with classes that rely on constructors for initial state setup—a common pattern in object-oriented design—we often run into a hurdle: standard mocking tools primarily focus on mocking methods (behavior), not the instantiation process itself.

This post will explore the correct and robust ways to control the arguments passed to a class constructor when creating a mock, ensuring your tests accurately reflect how dependent objects are initialized. We will dive into practical PHPUnit techniques and discuss broader dependency management principles relevant to frameworks like Laravel.

The Challenge: Mocking Initialization State

Consider the scenario presented in the example: you have a class where the constructor sets crucial internal state (like a DateTime object), and you need your test setup to control this initial state without actually running the real, potentially complex, logic inside the constructor. If you only mock methods like getUsers(), the constructor runs with default values, which might lead to unexpected test failures if those defaults aren't what you intend to test against.

The goal is to use mocking to inject specific prerequisites into the object being tested.

The Solution: Controlling Constructor Arguments in PHPUnit

PHPUnit provides a dedicated mechanism for achieving this control through the setConstructorArgs() method when building mocks. This method allows you to explicitly define the arguments that will be passed when the mocked constructor is called during object instantiation.

Step-by-Step Implementation

To successfully pass arguments to a mocked constructor, follow these steps:

  1. Use getMockBuilder(): Start by instructing PHPUnit how you want to build your mock class.
  2. Define the Class: Specify the actual class you are mocking.
  3. Use setConstructorArgs(): Provide an array containing the exact arguments you wish to pass to the constructor.
  4. Use onlyMethods() (Optional but Recommended): If you only intend to mock specific methods, use this method to restrict mocking scope.

Let's apply this to your example, aiming to pass a specific date string ("2021-12-22") into the constructor so that getDay() returns the mocked value instead of the current system time.

use PHPUnit\Framework\TestCase;

class MyNotificationsTest extends TestCase
{
    public function testCustomDateInitialization()
    {
        $expectedDate = '2021-12-22';

        // 1. Build the mock, specifying which methods are mocked.
        $mock = $this->getMockBuilder(MyNotifications::class)
                     ->onlyMethods(['getDay']) // Only mock the method we need to control for testing simplicity
                     ->setConstructorArgs([$expectedDate]) // <-- THIS IS THE KEY STEP
                     ->getMock();

        // 2. Define the behavior of the mocked method (which will be called by getDay())
        $mock->method('getDay')->willReturn(22); // Return the desired day number

        // When $mock is instantiated, it used '2021-12-22' as the initial date.
        $result = $mock->getDay();

        // Assert the controlled behavior
        $this->assertEquals(22, $result);
    }
}

Explanation and Best Practices

By using setConstructorArgs([$expectedDate]), we ensure that when $mock is created (e.g., $mock = new MyNotifications($expectedDate)), the constructor logic inside MyNotifications receives the value we specified, effectively setting the internal state exactly as required for our test.

This technique is powerful because it allows you to test how your class behaves given a specific initial condition, which is crucial when dealing with classes that adhere to SOLID principles—especially when managing dependencies. In modern PHP development, understanding dependency injection (DI) and mocking these initialization steps is fundamental, much like ensuring robust service contracts in frameworks such as Laravel where services are often injected via the container.

Conclusion

Passing arguments to a mocked class constructor is not just an arcane trick; it is a necessary skill for writing effective unit tests that isolate behavior from setup logic. By leveraging methods like setConstructorArgs(), you gain fine-grained control over object initialization, allowing you to test complex object states reliably. Always aim to mock the dependencies your class relies on, whether they are simple method calls or the initial state provided by a constructor. Master this technique, and your testing will become significantly more accurate and less brittle.