I originally sent this article to my subscribers as a newsletter on December 5, 2025. Since then, I have revised it to reflect changes following the release of PHPUnit 12.5. You can find more information about my newsletter at the end of this article.
Mock Objects without expectations
PHPUnit now emits a notice when a test method creates a mock object using createMock(), for example, but fails to configure an expectation on it. This useful diagnostic feature highlights a common oversight in test code.
This change addresses a key principle of software testing: the difference between test stubs and mock objects. Mock objects are specifically designed to verify communication between collaborating objects. If you create a mock object but never verify communication through expectations, it is likely that you are using the wrong type of test double.
Important: In its default configuration, PHPUnit does not display the details of this notice. Furthermore, using a mock object without configured expectations does not cause PHPUnit to terminate with a shell exit code that signals the failure of the test suite. However, both behaviours can be specifically enabled: either by setting displayDetailsOnPhpunitNotices="true" and failOnPhpunitNotice="true" in the XML configuration, or by using the CLI options --display-phpunit-notices and --fail-on-phpunit-notice.
As detailed in my article "Testing with(out) dependencies", PHPUnit's evolution towards clarity has culminated in this explicit guidance. Rather than silently accepting unused mock objects, PHPUnit now prompts you to either verify the expected behaviour or reconsider using createStub() instead of createMock(). This nudge towards better testing practices helps to ensure that your test suite remains focused and intentional.
Why this matters? Testing is about intentional communication. Mock objects, like theatrical masks, are tools of deliberate expression. When you create a mock object but do not configure expectations, you're creating a mask with no purpose: a performance without intent. PHPUnit 12.5's new notice asks developers to reconsider whether that mask is actually serving a role in your testing narrative.
Recognising that real-world test suites often rely on shared initialisation logic, PHPUnit 12.5 introduced the #[AllowMockObjectsWithoutExpectations] attribute in an effort to help developers who create mock objects in a before-test method to reduce code duplication across multiple tests. In such scenarios, a single test double may act as a mock object with expectations in one test method, but merely as a test stub in another. As a mock object cannot be changed into a test stub, this attribute provides a pragmatic way to opt out of the notice in specific contexts and on a test-by-test basis. It ensures that PHPUnit's strictness encourages better design without hindering valid, established testing patterns such as shared test fixtures or abstract base classes for test case classes.
There are edge cases where PHPUnit issues the above-described notice even though we would not expect it to. If we understand how PHPUnit handles mock objects internally, this notice will not be confusing in such situations: Every mock object created during a test is verified at the end of the test, regardless of whether the test code still holds a reference to it. I have explained this in more detail here.
Enhanced flexibility: --all CLI option
The --all CLI option can now be used to override test selection configured in your XML configuration file. This is particularly useful when running utility commands such as --list-suites, --list-groups, or --list-tests.
This gives you more flexibility in how you control test execution from the command line, regardless of what your configuration file specifies.
Preparing for the Future: PHPUnit 13
PHPUnit 12.5 was the final feature release of the PHPUnit 12 series. PHPUnit 13 will be released in February 2026.
If you have not already reviewed the deprecations, now is the time to do so. The DEPRECATIONS.md file on GitHub details all the deprecated features that you should address in your test suite to ensure a smooth transition to PHPUnit 13.
Addressing these deprecations now will give you a head start and prevent any surprises when PHPUnit 13 is released.
Exclusive insights delivered to your inbox
Coinciding with each PHPUnit feature release every two months, I deliver a comprehensive analysis of new features, implementation details, and the strategic reasoning behind every enhancement directly to subscribers. It's more than just a ChangeLog: it's your gateway to understanding how cutting-edge testing capabilities can transform your development workflow.
I publish the content of the newsletter here on this website a month after my subscribers have received it. Subscribe now to ensure you receive valuable information about PHPUnit as soon as possible.