phpunit: Exception: "Cannot find TestCase object on call stack" (with example)

Q A
PHPUnit version 10.2.0
PHP version 8.2.6
Installation Method Composer

Summary

Note: I apologise, I originally wrote this issue when using orchestra/testbench (Laravel). However I dug further into Laravel to find out the relevant factor (it sets an error handler), and have updated this issue to use only PHPUnit. The original post is included at the end.

Hi there. I found a situation which causes PHPUnit to throw an exception.

NoTestCaseObjectOnCallStackException with message “Cannot find TestCase object on call stack”.

Current behavior

I’ve been able to reproduce this in a particular circumstance:

  • There are at least two test classes
  • The first one (aphabetically) registers an error handler
  • PHPUnit is run with the --filter=xxx option that includes the first test

A NoTestCaseObjectOnCallStackException is thrown, with the output:

An error occurred inside PHPUnit.

Message:  Cannot find TestCase object on call stack
Location: /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:68

#0 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#1 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/phpunit(99): PHPUnit\TextUI\Application->run(Array)
#2 /var/www/html/code-distortion/phpunit-bug/vendor/bin/phpunit(122): include('/var/www/html/c...')
#3 {main}

Caused by: /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php:62

#0 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php(72): PHPUnit\Event\Code\TestMethodBuilder::fromCallStack()
#1 [internal function]: PHPUnit\Runner\ErrorHandler->__invoke(2, 'preg_match(): D...', '/var/www/html/c...', 75)
#2 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php(75): preg_match('test_something', '')
#3 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php(41): PHPUnit\Runner\Filter\NameFilterIterator->setFilter('test_something')
#4 [internal function]: PHPUnit\Runner\Filter\NameFilterIterator->__construct(Object(PHPUnit\Framework\TestSuiteIterator), 'test_something', Object(PHPUnit\Framework\TestSuite))
#5 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php(53): ReflectionClass->newInstance(Object(PHPUnit\Framework\TestSuiteIterator), 'test_something', Object(PHPUnit\Framework\TestSuite))
#6 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(386): PHPUnit\Runner\Filter\Factory->factory(Object(PHPUnit\Framework\TestSuiteIterator), Object(PHPUnit\Framework\TestSuite))
#7 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(272): PHPUnit\Framework\TestSuite->getIterator()
#8 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(320): PHPUnit\Framework\TestSuite->count()
#9 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#10 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#11 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(63): PHPUnit\Framework\TestSuite->run()
#12 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#13 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/phpunit(99): PHPUnit\TextUI\Application->run(Array)
#14 /var/www/html/code-distortion/phpunit-bug/vendor/bin/phpunit(122): include('/var/www/html/c...')
#15 {main}

How to reproduce

I created a repo to demonstrate this issue, please refer to that for a working example.

  1. Create two test classes. The first one (alphabetically) will register an error handler.
<?php
// ATest.php

use PHPUnit\Framework\TestCase;

class ATest extends TestCase
{
    public static function test_something_a(): void
    {
        set_error_handler([self::class, 'handleError']);

        print "\n\"Running ATest::test_something_a()\"\n";

        self::assertTrue(true);
    }

    public static function handleError(
        int $errno,
        string $errstr,
        string $errfile = '',
        int $errline = 0,
        array $errcontext = [],
    ): void {
        print "This won't be called";
    }
}
<?php
// BTest.php

use PHPUnit\Framework\TestCase;

class BTest extends TestCase
{
    public static function test_something_b(): void
    {
        print "\n\"Running BTest::test_something_b()\"\n";

        self::assertTrue(true);
    }
}
  1. Run the tests with the --filter=xxx option, so that it includes ATest:
./vendor/bin/phpunit --filter=test_something

Expected behavior

The tests should run without the exception being thrown.

Observations

These are the steps leading up to the exception being thrown:

  1. PHPUnit\Runner\Filter\NameFilterIterator:75 generates (a suppressed) PHP warning “preg_match(): Delimiter must not be alphanumeric, backslash, or NUL”
  2. PHPUnit\Runner\ErrorHandler:71 handles this warning, and calls PHPUnit\Event\Code\TestMethodBuilder::fromCallStack()
  3. The exception is triggered by PHPUnit\Event\Code\TestMethodBuilder:62 when it isn’t able to find a TestCase class in the PHP stack trace.

Changes that cause the exception to not occur:

  • Changing the order of ATest and BTest (by renaming them), or
  • Removing BTest, or
  • Running phpunit with --filter=xxx that doesn’t include ATest, or
  • Running phpunit without the --filter=xxx option

This doesn’t seem to occur with phpunit ^9.0.


⚙️ As requested, here is the `composer info` output
$ composer info | sort
myclabs/deep-copy                  1.11.1  Create deep copies (clones) of your objects
nikic/php-parser                   v4.15.5 A PHP parser written in PHP
phar-io/manifest                   2.0.3   Component for reading phar.io manifest information from a PHP Archive (PHAR)
phar-io/version                    3.2.1   Library for handling version information and constraints
phpunit/php-code-coverage          10.1.2  Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator          4.0.2   FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker                4.0.0   Invoke callables with a timeout
phpunit/php-text-template          3.0.0   Simple template engine.
phpunit/php-timer                  6.0.0   Utility class for timing
phpunit/phpunit                    10.2.0  The PHP Unit Testing framework.
sebastian/cli-parser               2.0.0   Library for parsing CLI options
sebastian/code-unit                2.0.0   Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup 3.0.0   Looks up which function or method a line of code belongs to
sebastian/comparator               5.0.0   Provides the functionality to compare PHP values for equality
sebastian/complexity               3.0.0   Library for calculating the complexity of PHP code units
sebastian/diff                     5.0.3   Diff implementation
sebastian/environment              6.0.1   Provides functionality to handle HHVM/PHP environments
sebastian/exporter                 5.0.0   Provides the functionality to export PHP variables for visualization
sebastian/global-state             6.0.0   Snapshotting of global state
sebastian/lines-of-code            2.0.0   Library for counting the lines of code in PHP source code
sebastian/object-enumerator        5.0.0   Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector         3.0.0   Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context        5.0.0   Provides functionality to recursively process PHP variables
sebastian/type                     4.0.0   Collection of value objects that represent the types of the PHP type system
sebastian/version                  4.0.1   Library that helps with managing the version number of Git-hosted PHP projects
theseer/tokenizer                  1.2.1   A small library for converting tokenized PHP source code into XML and potentially other formats

⚙️ Click to see the original issue, that included orchestra/testbench
Q A
PHPUnit version 10.2.0
PHP version 8.2.6
Installation Method Composer
OrchestraTestbench v8.5.5

Summary

Hi there. I found a situation which causes PHPUnit to throw an exception.

NoTestCaseObjectOnCallStackException with message “Cannot find TestCase object on call stack”.

Current behavior

I’ve been able to reproduce this in a particular circumstance:

  • There are at least two test classes
  • The first one (aphabetically) extends Orchestra\Testbench\TestCase (which itself extends from PHPUnit\Framework\TestCase)
  • PHPUnit is run with the --filter=xxx option that includes the first test

A NoTestCaseObjectOnCallStackException is thrown, with the output:

An error occurred inside PHPUnit.

Message:  Cannot find TestCase object on call stack
Location: /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:68

#0 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#1 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/phpunit(99): PHPUnit\TextUI\Application->run(Array)
#2 /var/www/html/code-distortion/phpunit-bug/vendor/bin/phpunit(122): include('/var/www/html/c...')
#3 {main}

Caused by: /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php:62

#0 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php(71): PHPUnit\Event\Code\TestMethodBuilder::fromCallStack()
#1 [internal function]: PHPUnit\Runner\ErrorHandler->__invoke(2, 'preg_match(): D...', '/var/www/html/c...', 75)
#2 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php(75): preg_match('test_something', '')
#3 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php(41): PHPUnit\Runner\Filter\NameFilterIterator->setFilter('test_something')
#4 [internal function]: PHPUnit\Runner\Filter\NameFilterIterator->__construct(Object(PHPUnit\Framework\TestSuiteIterator), 'test_something', Object(PHPUnit\Framework\TestSuite))
#5 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php(53): ReflectionClass->newInstance(Object(PHPUnit\Framework\TestSuiteIterator), 'test_something', Object(PHPUnit\Framework\TestSuite))
#6 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(386): PHPUnit\Runner\Filter\Factory->factory(Object(PHPUnit\Framework\TestSuiteIterator), Object(PHPUnit\Framework\TestSuite))
#7 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(272): PHPUnit\Framework\TestSuite->getIterator()
#8 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(320): PHPUnit\Framework\TestSuite->count()
#9 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#10 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#11 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(63): PHPUnit\Framework\TestSuite->run()
#12 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#13 /var/www/html/code-distortion/phpunit-bug/vendor/phpunit/phpunit/phpunit(99): PHPUnit\TextUI\Application->run(Array)
#14 /var/www/html/code-distortion/phpunit-bug/vendor/bin/phpunit(122): include('/var/www/html/c...')
#15 {main}

How to reproduce

I created a repo to demonstrate this issue, please refer to that for a working example.

  1. Install Orchestra\Testbench:
composer require orchestra/testbench:^8.0
  1. Create two test classes. The first one (alphabetically) will extend from Orchestra\Testbench\TestCase. The second can extend from either that, or PHPUnit\Framework\TestCase.
<?php
// ATest.php

use Orchestra\Testbench\TestCase as TestCase;
//use PHPUnit\Framework\TestCase;

class ATest extends TestCase
{
    public static function test_something_a(): void
    {
        dump('running ATest::test_something_a');
        self::assertTrue(true);
    }
}
<?php
// BTest.php

//use Orchestra\Testbench\TestCase as TestCase;
use PHPUnit\Framework\TestCase;

class BTest extends TestCase
{
    public static function test_something_b(): void
    {
        dump('running BTest::test_something_b');
        self::assertTrue(true);
    }
}
  1. Run the tests with the --filter=xxx option, so that it includes the first test:
./vendor/bin/phpunit --filter=test_something

Expected behavior

The tests should run without the exception being thrown.

Observations

Although orchestra/testbench is used to trigger the error, it seems to be related to the way PHPUnit handles a PHP warning that Testbench generates.

These are the steps leading up to the exception being thrown:

  1. Testbench generates PHP warning: “file_get_contents(/var/www/html/code-distortion/phpunit-bug/vendor/orchestra/testbench-core/laravel/.env): Failed to open stream: No such file or directory”
  2. PHPUnit\Runner\ErrorHandler:71 handles this warning, and calls PHPUnit\Event\Code\TestMethodBuilder::fromCallStack()
  3. The exception is triggered by PHPUnit\Event\Code\TestMethodBuilder:62 when it isn’t able to find a TestCase class in the PHP stack trace.

Changes that cause the exception to not occur:

  • Changing the order of ATest and BTest (by renaming them), or
  • Updating ATest to extend from PHPUnit\Framework\TestCase, or
  • Removing BTest, or
  • Running phpunit with --filter=xxx that doesn’t include the first test, or
  • Running phpunit without the --filter=xxx option

This doesn’t seem to occur with earlier versions, when either orchestra/testbench ^7.0, or phpunit ^9.0 is used.


⚙️ As requested, here is the `composer info` output
$ composer info | sort
brick/math                         0.11.0   Arbitrary-precision arithmetic library
dflydev/dot-access-data            v3.0.2   Given a deep data structure, access data by dot notation.
doctrine/inflector                 2.0.6    PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/lexer                     3.0.0    PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
dragonmantank/cron-expression      v3.3.2   CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due
egulias/email-validator            4.0.1    A library for validating emails against several RFCs
fakerphp/faker                     v1.22.0  Faker is a PHP library that generates fake data for you.
fruitcake/php-cors                 v1.2.0   Cross-origin resource sharing library for the Symfony HttpFoundation
graham-campbell/result-type        v1.1.1   An Implementation Of The Result Type
guzzlehttp/psr7                    2.5.0    PSR-7 message implementation that also provides common utility methods
guzzlehttp/uri-template            v1.0.1   A polyfill class for uri_template of PHP
hamcrest/hamcrest-php              v2.0.1   This is the PHP port of Hamcrest Matchers
laravel/framework                  v10.13.1 The Laravel Framework.
laravel/serializable-closure       v1.3.0   Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.
league/commonmark                  2.4.0    Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)
league/config                      v1.2.0   Define configuration arrays with strict schemas and access values with dot notation
league/flysystem                   3.15.1   File storage abstraction for PHP
league/flysystem-local             3.15.0   Local filesystem adapter for Flysystem.
league/mime-type-detection         1.11.0   Mime-type detection for Flysystem
mockery/mockery                    1.5.1    Mockery is a simple yet flexible PHP mock object framework
monolog/monolog                    3.3.1    Sends your logs to files, sockets, inboxes, databases and various web services
myclabs/deep-copy                  1.11.1   Create deep copies (clones) of your objects
nesbot/carbon                      2.67.0   An API extension for DateTime that supports 281 different languages.
nette/schema                       v1.2.3   📐 Nette Schema: validating data structures against a given Schema.
nette/utils                        v4.0.0   🛠  Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password gener...
nikic/php-parser                   v4.15.5  A PHP parser written in PHP
nunomaduro/termwind                v1.15.1  Its like Tailwind CSS, but for the console.
orchestra/testbench                v8.5.5   Laravel Testing Helper for Packages Development
orchestra/testbench-core           v8.5.3   Testing Helper for Laravel Development
phar-io/manifest                   2.0.3    Component for reading phar.io manifest information from a PHP Archive (PHAR)
phar-io/version                    3.2.1    Library for handling version information and constraints
phpoption/phpoption                1.9.1    Option Type for PHP
phpunit/php-code-coverage          10.1.2   Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator          4.0.2    FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker                4.0.0    Invoke callables with a timeout
phpunit/php-text-template          3.0.0    Simple template engine.
phpunit/php-timer                  6.0.0    Utility class for timing
phpunit/phpunit                    10.2.0   The PHP Unit Testing framework.
pimple/pimple                      v3.5.0   Pimple, a simple Dependency Injection Container
psr/container                      2.0.2    Common Container Interface (PHP FIG PSR-11)
psr/event-dispatcher               1.0.0    Standard interfaces for event handling.
psr/http-factory                   1.0.2    Common interfaces for PSR-7 HTTP message factories
psr/http-message                   2.0      Common interface for HTTP messages
psr/log                            3.0.0    Common interface for logging libraries
psr/simple-cache                   3.0.0    Common interfaces for simple caching
ralouphie/getallheaders            3.0.3    A polyfill for getallheaders.
ramsey/collection                  2.0.0    A PHP library for representing and manipulating collections.
ramsey/uuid                        4.7.4    A PHP library for generating and working with universally unique identifiers (UUIDs).
sebastian/cli-parser               2.0.0    Library for parsing CLI options
sebastian/code-unit                2.0.0    Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup 3.0.0    Looks up which function or method a line of code belongs to
sebastian/comparator               5.0.0    Provides the functionality to compare PHP values for equality
sebastian/complexity               3.0.0    Library for calculating the complexity of PHP code units
sebastian/diff                     5.0.3    Diff implementation
sebastian/environment              6.0.1    Provides functionality to handle HHVM/PHP environments
sebastian/exporter                 5.0.0    Provides the functionality to export PHP variables for visualization
sebastian/global-state             6.0.0    Snapshotting of global state
sebastian/lines-of-code            2.0.0    Library for counting the lines of code in PHP source code
sebastian/object-enumerator        5.0.0    Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector         3.0.0    Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context        5.0.0    Provides functionality to recursively process PHP variables
sebastian/type                     4.0.0    Collection of value objects that represent the types of the PHP type system
sebastian/version                  4.0.1    Library that helps with managing the version number of Git-hosted PHP projects
spatie/backtrace                   1.4.0    A better backtrace
spatie/laravel-ray                 1.32.4   Easily debug Laravel apps
spatie/macroable                   2.0.0    A trait to dynamically add methods to a class
spatie/ray                         1.37.2   Debug with Ray to fix problems faster
symfony/console                    v6.3.0   Eases the creation of beautiful and testable command line interfaces
symfony/css-selector               v6.3.0   Converts CSS selectors to XPath expressions
symfony/deprecation-contracts      v3.3.0   A generic function and convention to trigger deprecation notices
symfony/error-handler              v6.3.0   Provides tools to manage errors and ease debugging PHP code
symfony/event-dispatcher           v6.3.0   Provides tools that allow your application components to communicate with each other by dispatching events and listening to them
symfony/event-dispatcher-contracts v3.3.0   Generic abstractions related to dispatching event
symfony/finder                     v6.3.0   Finds files and directories via an intuitive fluent interface
symfony/http-foundation            v6.3.0   Defines an object-oriented layer for the HTTP specification
symfony/http-kernel                v6.3.0   Provides a structured process for converting a Request into a Response
symfony/mailer                     v6.3.0   Helps sending emails
symfony/mime                       v6.3.0   Allows manipulating MIME messages
symfony/polyfill-ctype             v1.27.0  Symfony polyfill for ctype functions
symfony/polyfill-iconv             v1.27.0  Symfony polyfill for the Iconv extension
symfony/polyfill-intl-grapheme     v1.27.0  Symfony polyfill for intl's grapheme_* functions
symfony/polyfill-intl-idn          v1.27.0  Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions
symfony/polyfill-intl-normalizer   v1.27.0  Symfony polyfill for intl's Normalizer class and related functions
symfony/polyfill-mbstring          v1.27.0  Symfony polyfill for the Mbstring extension
symfony/polyfill-php72             v1.27.0  Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/polyfill-php80             v1.27.0  Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions
symfony/polyfill-php83             v1.27.0  Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions
symfony/polyfill-uuid              v1.27.0  Symfony polyfill for uuid functions
symfony/process                    v6.3.0   Executes commands in sub-processes
symfony/routing                    v6.3.0   Maps an HTTP request to a set of configuration variables
symfony/service-contracts          v3.3.0   Generic abstractions related to writing services
symfony/stopwatch                  v6.3.0   Provides a way to profile code
symfony/string                     v6.3.0   Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way
symfony/translation                v6.3.0   Provides tools to internationalize your application
symfony/translation-contracts      v3.3.0   Generic abstractions related to translation
symfony/uid                        v6.3.0   Provides an object-oriented API to generate and represent UIDs
symfony/var-dumper                 v6.3.0   Provides mechanisms for walking through any arbitrary PHP variable
symfony/yaml                       v6.3.0   Loads and dumps YAML files
theseer/tokenizer                  1.2.1    A small library for converting tokenized PHP source code into XML and potentially other formats
tijsverkoyen/css-to-inline-styles  2.2.6    CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.
vlucas/phpdotenv                   v5.5.0   Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.
voku/portable-ascii                2.0.1    Portable ASCII library - performance optimized (ascii) string functions for php.
webmozart/assert                   1.11.0   Assertions to validate method input/output with nice error messages.
zbateson/mail-mime-parser          2.4.0    MIME email message parser
zbateson/mb-wrapper                1.2.0    Wrapper for mbstring with fallback to iconv for encoding conversion and string manipulation
zbateson/stream-decorators         1.2.1    PHP psr7 stream decorators for mime message part streams

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (2 by maintainers)

Commits related to this issue

Most upvoted comments

I’ve been stuck on this issue for over a week and now I’ve discovered a solution.

In my tested classes, set_error_handler is set and in PHP 8.3 the following exception appeared:

Cannot find TestCase object on call stack

This happens because phpunit conflicts with your custom error handler.

The solution is to call the restore_error_handler() function before performing the tests.

This issue happened in PHPUnit ^10.2 and only with PHP 8.3. With PHP 8.1 and 8.2 this issue does not appear.

I’m still having this problem right now with laravel 10.37.1 and phpunit 10.5.2

Fixed on Pest v2.8.1.

Please understand that I cannot investigate problems that involve third-party extensions for / wrappers around PHPUnit such as Pest.

Definitely, that’s not your job! I was just not aware that this is PEST specific and should be handled there, as downgrading to PHPUnit v10.1.3 fixed it. Thanks for your hard work on the gold standard testing framework in PHP!

I’m still having this problem right now with laravel 10.37.1 and phpunit 10.5.2

any solution? this is still happening. PHPUnit upgraded to latest version.

@sebastianbergmann Any hope of tagging a new release containing this fix anytime soon?

Hi @sebastianbergmann. Thanks for fixing this in v10.2.1. But I am still experiencing this bug in a Laravel 10 project with latest PEST v2.6.3 / PHPUnit v10.2.1, e.g.:

$ php artisan test --filter HasActiveFlagTest

   ERROR  Cannot find TestCase object on call stack

Location: vendor/phpunit/phpunit/src/TextUI/TestRunner.php:68

#0 vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#1 vendor/pestphp/pest/src/Kernel.php(86): PHPUnit\TextUI\Application->run(Array)
#2 vendor/pestphp/pest/bin/pest(91): Pest\Kernel->handle(Array)
#3 vendor/pestphp/pest/bin/pest(99): {closure}()
#4 {main}

Caused by: vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php:62

#0 vendor/phpunit/phpunit/src/Runner/ErrorHandler.php(76): PHPUnit\Event\Code\TestMethodBuilder::fromCallStack()
#1 [internal function]: PHPUnit\Runner\ErrorHandler->__invoke(2, 'preg_match(): D...', '/Users/phi/Site...', 103)
#2 vendor/pestphp/pest/overrides/Runner/Filter/NameFilterIterator.php(103): preg_match('HasActiveFlagTe...', '')
#3 vendor/pestphp/pest/overrides/Runner/Filter/NameFilterIterator.php(69): PHPUnit\Runner\Filter\NameFilterIterator->setFilter('HasActiveFlagTe...')
#4 [internal function]: PHPUnit\Runner\Filter\NameFilterIterator->__construct(Object(PHPUnit\Framework\TestSuiteIterator), 'HasActiveFlagTe...', Object(PHPUnit\Framework\TestSuite))
#5 vendor/phpunit/phpunit/src/Runner/Filter/Factory.php(53): ReflectionClass->newInstance(Object(PHPUnit\Framework\TestSuiteIterator), 'HasActiveFlagTe...', Object(PHPUnit\Framework\TestSuite))
#6 vendor/phpunit/phpunit/src/Framework/TestSuite.php(386): PHPUnit\Runner\Filter\Factory->factory(Object(PHPUnit\Framework\TestSuiteIterator), Object(PHPUnit\Framework\TestSuite))
#7 vendor/phpunit/phpunit/src/Framework/TestSuite.php(272): PHPUnit\Framework\TestSuite->getIterator()
#8 vendor/phpunit/phpunit/src/Framework/TestSuite.php(320): PHPUnit\Framework\TestSuite->count()
#9 vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#10 vendor/phpunit/phpunit/src/Framework/TestSuite.php(340): PHPUnit\Framework\TestSuite->run()
#11 vendor/phpunit/phpunit/src/TextUI/TestRunner.php(63): PHPUnit\Framework\TestSuite->run()
#12 vendor/phpunit/phpunit/src/TextUI/Application.php(168): PHPUnit\TextUI\TestRunner->run(Object(PHPUnit\TextUI\Configuration\Configuration), Object(PHPUnit\Runner\ResultCache\DefaultResultCache), Object(PHPUnit\Framework\TestSuite))
#13 vendor/pestphp/pest/src/Kernel.php(86): PHPUnit\TextUI\Application->run(Array)
#14 vendor/pestphp/pest/bin/pest(91): Pest\Kernel->handle(Array)
#15 vendor/pestphp/pest/bin/pest(99): {closure}()
#16 {main}.

as a workaround, I had to downgrade to PHPUnit v10.1.3, and that ERROR no longer pops up.

Also, others report the same, https://stackoverflow.com/a/76404292/5982842

I still get this error after upgrading to 10.2.1 😦 – St. Jan Jun 7 at 15:41

Thank you for bringing this up.

This happens because PHPUnit’s error handler tries to emit an event for the suppressed E_WARNING error triggered by preg_match() in NameFilterIterator. Somehow we missed that going from 758cdcce2682bda2b5b7958dd470537f8622f094 over 12340577a2719266b7072f3036db7488a00ff05c to #5326, #5293, and #5328.

As of 16166431bce84bb100d8e7fe867d612bdfe61776, PHPUnit’s error handler no longer emits events for suppressed errors in PHPUnit’s own code (or code of its dependencies).

It’s “interesting”, though, that the error you reported is only triggered when a test and/or the code under test registers its own error handler. But supporting custom error handlers (in addition to PHPUnit’s own error handler) is not a priority for me so I won’t investigate that further.

Your example work as expected as of 16166431bce84bb100d8e7fe867d612bdfe61776.