Вход Регистрация
Файл: vendor/phpunit/phpunit/src/Framework/TestCase.php
Строк: 2749
<?php declare(strict_types=1);
/*
 * This file is part of PHPUnit.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PHPUnitFramework;

use const 
LC_ALL;
use const 
LC_COLLATE;
use const 
LC_CTYPE;
use const 
LC_MONETARY;
use const 
LC_NUMERIC;
use const 
LC_TIME;
use const 
PATHINFO_FILENAME;
use const 
PHP_EOL;
use const 
PHP_URL_PATH;
use function 
array_filter;
use function 
array_flip;
use function 
array_keys;
use function 
array_merge;
use function 
array_pop;
use function 
array_search;
use function 
array_unique;
use function 
array_values;
use function 
basename;
use function 
call_user_func;
use function 
chdir;
use function 
class_exists;
use function 
clearstatcache;
use function 
count;
use function 
debug_backtrace;
use function 
defined;
use function 
explode;
use function 
get_class;
use function 
get_include_path;
use function 
getcwd;
use function 
implode;
use function 
in_array;
use function 
ini_set;
use function 
is_array;
use function 
is_callable;
use function 
is_int;
use function 
is_object;
use function 
is_string;
use function 
libxml_clear_errors;
use function 
method_exists;
use function 
ob_end_clean;
use function 
ob_get_contents;
use function 
ob_get_level;
use function 
ob_start;
use function 
parse_url;
use function 
pathinfo;
use function 
preg_replace;
use function 
serialize;
use function 
setlocale;
use function 
sprintf;
use function 
strpos;
use function 
substr;
use function 
trim;
use function 
var_export;
use 
DeepCopyDeepCopy;
use 
PHPUnitFrameworkConstraintException as ExceptionConstraint;
use 
PHPUnitFrameworkConstraintExceptionCode;
use 
PHPUnitFrameworkConstraintExceptionMessage;
use 
PHPUnitFrameworkConstraintExceptionMessageRegularExpression;
use 
PHPUnitFrameworkConstraintLogicalOr;
use 
PHPUnitFrameworkErrorDeprecated;
use 
PHPUnitFrameworkErrorError;
use 
PHPUnitFrameworkErrorNotice;
use 
PHPUnitFrameworkErrorWarning as WarningError;
use 
PHPUnitFrameworkMockObjectGenerator as MockGenerator;
use 
PHPUnitFrameworkMockObjectMockBuilder;
use 
PHPUnitFrameworkMockObjectMockObject;
use 
PHPUnitFrameworkMockObjectRuleAnyInvokedCount as AnyInvokedCountMatcher;
use 
PHPUnitFrameworkMockObjectRuleInvokedAtIndex as InvokedAtIndexMatcher;
use 
PHPUnitFrameworkMockObjectRuleInvokedAtLeastCount as InvokedAtLeastCountMatcher;
use 
PHPUnitFrameworkMockObjectRuleInvokedAtLeastOnce as InvokedAtLeastOnceMatcher;
use 
PHPUnitFrameworkMockObjectRuleInvokedAtMostCount as InvokedAtMostCountMatcher;
use 
PHPUnitFrameworkMockObjectRuleInvokedCount as InvokedCountMatcher;
use 
PHPUnitFrameworkMockObjectStub;
use 
PHPUnitFrameworkMockObjectStubConsecutiveCalls as ConsecutiveCallsStub;
use 
PHPUnitFrameworkMockObjectStubException as ExceptionStub;
use 
PHPUnitFrameworkMockObjectStubReturnArgument as ReturnArgumentStub;
use 
PHPUnitFrameworkMockObjectStubReturnCallback as ReturnCallbackStub;
use 
PHPUnitFrameworkMockObjectStubReturnSelf as ReturnSelfStub;
use 
PHPUnitFrameworkMockObjectStubReturnStub;
use 
PHPUnitFrameworkMockObjectStubReturnValueMap as ReturnValueMapStub;
use 
PHPUnitRunnerBaseTestRunner;
use 
PHPUnitRunnerPhptTestCase;
use 
PHPUnitUtilCloner;
use 
PHPUnitUtilException as UtilException;
use 
PHPUnitUtilGlobalState;
use 
PHPUnitUtilPHPAbstractPhpProcess;
use 
PHPUnitUtilTest as TestUtil;
use 
ProphecyExceptionPredictionPredictionException;
use 
ProphecyProphecyMethodProphecy;
use 
ProphecyProphecyObjectProphecy;
use 
ProphecyProphet;
use 
ReflectionClass;
use 
ReflectionException;
use 
SebastianBergmannComparatorComparator;
use 
SebastianBergmannComparatorFactory as ComparatorFactory;
use 
SebastianBergmannDiffDiffer;
use 
SebastianBergmannExporterExporter;
use 
SebastianBergmannGlobalStateExcludeList;
use 
SebastianBergmannGlobalStateRestorer;
use 
SebastianBergmannGlobalStateSnapshot;
use 
SebastianBergmannObjectEnumeratorEnumerator;
use 
SebastianBergmannTemplateTemplate;
use 
SoapClient;
use 
Throwable;

/**
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
 */
abstract class TestCase extends Assert implements ReorderableSelfDescribingTest
{
    private const 
LOCALE_CATEGORIES = [LC_ALLLC_COLLATELC_CTYPELC_MONETARYLC_NUMERICLC_TIME];

    
/**
     * @var ?bool
     */
    
protected $backupGlobals;

    
/**
     * @var string[]
     */
    
protected $backupGlobalsExcludeList = [];

    
/**
     * @var string[]
     *
     * @deprecated Use $backupGlobalsExcludeList instead
     */
    
protected $backupGlobalsBlacklist = [];

    
/**
     * @var bool
     */
    
protected $backupStaticAttributes;

    
/**
     * @var array<string,array<int,string>>
     */
    
protected $backupStaticAttributesExcludeList = [];

    
/**
     * @var array<string,array<int,string>>
     *
     * @deprecated Use $backupStaticAttributesExcludeList instead
     */
    
protected $backupStaticAttributesBlacklist = [];

    
/**
     * @var bool
     */
    
protected $runTestInSeparateProcess;

    
/**
     * @var bool
     */
    
protected $preserveGlobalState true;

    
/**
     * @var list<ExecutionOrderDependency>
     */
    
protected $providedTests = [];

    
/**
     * @var bool
     */
    
private $runClassInSeparateProcess;

    
/**
     * @var bool
     */
    
private $inIsolation false;

    
/**
     * @var array
     */
    
private $data;

    
/**
     * @var int|string
     */
    
private $dataName;

    
/**
     * @var null|string
     */
    
private $expectedException;

    
/**
     * @var null|string
     */
    
private $expectedExceptionMessage;

    
/**
     * @var null|string
     */
    
private $expectedExceptionMessageRegExp;

    
/**
     * @var null|int|string
     */
    
private $expectedExceptionCode;

    
/**
     * @var string
     */
    
private $name '';

    
/**
     * @var list<ExecutionOrderDependency>
     */
    
private $dependencies = [];

    
/**
     * @var array
     */
    
private $dependencyInput = [];

    
/**
     * @var array<string,string>
     */
    
private $iniSettings = [];

    
/**
     * @var array
     */
    
private $locale = [];

    
/**
     * @var MockObject[]
     */
    
private $mockObjects = [];

    
/**
     * @var MockGenerator
     */
    
private $mockObjectGenerator;

    
/**
     * @var int
     */
    
private $status BaseTestRunner::STATUS_UNKNOWN;

    
/**
     * @var string
     */
    
private $statusMessage '';

    
/**
     * @var int
     */
    
private $numAssertions 0;

    
/**
     * @var TestResult
     */
    
private $result;

    
/**
     * @var mixed
     */
    
private $testResult;

    
/**
     * @var string
     */
    
private $output '';

    
/**
     * @var ?string
     */
    
private $outputExpectedRegex;

    
/**
     * @var ?string
     */
    
private $outputExpectedString;

    
/**
     * @var mixed
     */
    
private $outputCallback false;

    
/**
     * @var bool
     */
    
private $outputBufferingActive false;

    
/**
     * @var int
     */
    
private $outputBufferingLevel;

    
/**
     * @var bool
     */
    
private $outputRetrievedForAssertion false;

    
/**
     * @var ?Snapshot
     */
    
private $snapshot;

    
/**
     * @var ProphecyProphet
     */
    
private $prophet;

    
/**
     * @var bool
     */
    
private $beStrictAboutChangesToGlobalState false;

    
/**
     * @var bool
     */
    
private $registerMockObjectsFromTestArgumentsRecursively false;

    
/**
     * @var string[]
     */
    
private $warnings = [];

    
/**
     * @var string[]
     */
    
private $groups = [];

    
/**
     * @var bool
     */
    
private $doesNotPerformAssertions false;

    
/**
     * @var Comparator[]
     */
    
private $customComparators = [];

    
/**
     * @var string[]
     */
    
private $doubledTypes = [];

    
/**
     * Returns a matcher that matches when the method is executed
     * zero or more times.
     */
    
public static function any(): AnyInvokedCountMatcher
    
{
        return new 
AnyInvokedCountMatcher;
    }

    
/**
     * Returns a matcher that matches when the method is never executed.
     */
    
public static function never(): InvokedCountMatcher
    
{
        return new 
InvokedCountMatcher(0);
    }

    
/**
     * Returns a matcher that matches when the method is executed
     * at least N times.
     */
    
public static function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher
    
{
        return new 
InvokedAtLeastCountMatcher(
            
$requiredInvocations
        
);
    }

    
/**
     * Returns a matcher that matches when the method is executed at least once.
     */
    
public static function atLeastOnce(): InvokedAtLeastOnceMatcher
    
{
        return new 
InvokedAtLeastOnceMatcher;
    }

    
/**
     * Returns a matcher that matches when the method is executed exactly once.
     */
    
public static function once(): InvokedCountMatcher
    
{
        return new 
InvokedCountMatcher(1);
    }

    
/**
     * Returns a matcher that matches when the method is executed
     * exactly $count times.
     */
    
public static function exactly(int $count): InvokedCountMatcher
    
{
        return new 
InvokedCountMatcher($count);
    }

    
/**
     * Returns a matcher that matches when the method is executed
     * at most N times.
     */
    
public static function atMost(int $allowedInvocations): InvokedAtMostCountMatcher
    
{
        return new 
InvokedAtMostCountMatcher($allowedInvocations);
    }

    
/**
     * Returns a matcher that matches when the method is executed
     * at the given index.
     *
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4297
     *
     * @codeCoverageIgnore
     */
    
public static function at(int $index): InvokedAtIndexMatcher
    
{
        
$stack debug_backtrace();

        while (!empty(
$stack)) {
            
$frame array_pop($stack);

            if (isset(
$frame['object']) && $frame['object'] instanceof self) {
                
$frame['object']->addWarning(
                    
'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.'
                
);

                break;
            }
        }

        return new 
InvokedAtIndexMatcher($index);
    }

    public static function 
returnValue($value): ReturnStub
    
{
        return new 
ReturnStub($value);
    }

    public static function 
returnValueMap(array $valueMap): ReturnValueMapStub
    
{
        return new 
ReturnValueMapStub($valueMap);
    }

    public static function 
returnArgument(int $argumentIndex): ReturnArgumentStub
    
{
        return new 
ReturnArgumentStub($argumentIndex);
    }

    public static function 
returnCallback($callback): ReturnCallbackStub
    
{
        return new 
ReturnCallbackStub($callback);
    }

    
/**
     * Returns the current object.
     *
     * This method is useful when mocking a fluent interface.
     */
    
public static function returnSelf(): ReturnSelfStub
    
{
        return new 
ReturnSelfStub;
    }

    public static function 
throwException(Throwable $exception): ExceptionStub
    
{
        return new 
ExceptionStub($exception);
    }

    public static function 
onConsecutiveCalls(...$args): ConsecutiveCallsStub
    
{
        return new 
ConsecutiveCallsStub($args);
    }

    
/**
     * @param int|string $dataName
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function __construct(?string $name null, array $data = [], $dataName '')
    {
        if (
$name !== null) {
            
$this->setName($name);
        }

        
$this->data     $data;
        
$this->dataName $dataName;
    }

    
/**
     * This method is called before the first test of this test class is run.
     */
    
public static function setUpBeforeClass(): void
    
{
    }

    
/**
     * This method is called after the last test of this test class is run.
     */
    
public static function tearDownAfterClass(): void
    
{
    }

    
/**
     * This method is called before each test.
     */
    
protected function setUp(): void
    
{
    }

    
/**
     * Performs assertions shared by all tests of a test case.
     *
     * This method is called between setUp() and test.
     */
    
protected function assertPreConditions(): void
    
{
    }

    
/**
     * Performs assertions shared by all tests of a test case.
     *
     * This method is called between test and tearDown().
     */
    
protected function assertPostConditions(): void
    
{
    }

    
/**
     * This method is called after each test.
     */
    
protected function tearDown(): void
    
{
    }

    
/**
     * Returns a string representation of the test case.
     *
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     * @throws Exception
     */
    
public function toString(): string
    
{
        try {
            
$class = new ReflectionClass($this);
            
// @codeCoverageIgnoreStart
        
} catch (ReflectionException $e) {
            throw new 
Exception(
                
$e->getMessage(),
                
$e->getCode(),
                
$e
            
);
        }
        
// @codeCoverageIgnoreEnd

        
$buffer sprintf(
            
'%s::%s',
            
$class->name,
            
$this->getName(false)
        );

        return 
$buffer $this->getDataSetAsString();
    }

    public function 
count(): int
    
{
        return 
1;
    }

    public function 
getActualOutputForAssertion(): string
    
{
        
$this->outputRetrievedForAssertion true;

        return 
$this->getActualOutput();
    }

    public function 
expectOutputRegex(string $expectedRegex): void
    
{
        
$this->outputExpectedRegex $expectedRegex;
    }

    public function 
expectOutputString(string $expectedString): void
    
{
        
$this->outputExpectedString $expectedString;
    }

    
/**
     * @psalm-param class-string<Throwable> $exception
     */
    
public function expectException(string $exception): void
    
{
        
// @codeCoverageIgnoreStart
        
switch ($exception) {
            case 
Deprecated::class:
                
$this->addWarning('Support for using expectException() with PHPUnitFrameworkErrorDeprecated is deprecated and will be removed in PHPUnit 10. Use expectDeprecation() instead.');

                break;

            case 
Error::class:
                
$this->addWarning('Support for using expectException() with PHPUnitFrameworkErrorError is deprecated and will be removed in PHPUnit 10. Use expectError() instead.');

                break;

            case 
Notice::class:
                
$this->addWarning('Support for using expectException() with PHPUnitFrameworkErrorNotice is deprecated and will be removed in PHPUnit 10. Use expectNotice() instead.');

                break;

            case 
WarningError::class:
                
$this->addWarning('Support for using expectException() with PHPUnitFrameworkErrorWarning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.');

                break;
        }
        
// @codeCoverageIgnoreEnd

        
$this->expectedException $exception;
    }

    
/**
     * @param int|string $code
     */
    
public function expectExceptionCode($code): void
    
{
        
$this->expectedExceptionCode $code;
    }

    public function 
expectExceptionMessage(string $message): void
    
{
        
$this->expectedExceptionMessage $message;
    }

    public function 
expectExceptionMessageMatches(string $regularExpression): void
    
{
        
$this->expectedExceptionMessageRegExp $regularExpression;
    }

    
/**
     * Sets up an expectation for an exception to be raised by the code under test.
     * Information for expected exception class, expected exception message, and
     * expected exception code are retrieved from a given Exception object.
     */
    
public function expectExceptionObject(Exception $exception): void
    
{
        
$this->expectException(get_class($exception));
        
$this->expectExceptionMessage($exception->getMessage());
        
$this->expectExceptionCode($exception->getCode());
    }

    public function 
expectNotToPerformAssertions(): void
    
{
        
$this->doesNotPerformAssertions true;
    }

    public function 
expectDeprecation(): void
    
{
        
$this->expectedException Deprecated::class;
    }

    public function 
expectDeprecationMessage(string $message): void
    
{
        
$this->expectExceptionMessage($message);
    }

    public function 
expectDeprecationMessageMatches(string $regularExpression): void
    
{
        
$this->expectExceptionMessageMatches($regularExpression);
    }

    public function 
expectNotice(): void
    
{
        
$this->expectedException Notice::class;
    }

    public function 
expectNoticeMessage(string $message): void
    
{
        
$this->expectExceptionMessage($message);
    }

    public function 
expectNoticeMessageMatches(string $regularExpression): void
    
{
        
$this->expectExceptionMessageMatches($regularExpression);
    }

    public function 
expectWarning(): void
    
{
        
$this->expectedException WarningError::class;
    }

    public function 
expectWarningMessage(string $message): void
    
{
        
$this->expectExceptionMessage($message);
    }

    public function 
expectWarningMessageMatches(string $regularExpression): void
    
{
        
$this->expectExceptionMessageMatches($regularExpression);
    }

    public function 
expectError(): void
    
{
        
$this->expectedException Error::class;
    }

    public function 
expectErrorMessage(string $message): void
    
{
        
$this->expectExceptionMessage($message);
    }

    public function 
expectErrorMessageMatches(string $regularExpression): void
    
{
        
$this->expectExceptionMessageMatches($regularExpression);
    }

    public function 
getStatus(): int
    
{
        return 
$this->status;
    }

    public function 
markAsRisky(): void
    
{
        
$this->status BaseTestRunner::STATUS_RISKY;
    }

    public function 
getStatusMessage(): string
    
{
        return 
$this->statusMessage;
    }

    public function 
hasFailed(): bool
    
{
        
$status $this->getStatus();

        return 
$status === BaseTestRunner::STATUS_FAILURE || $status === BaseTestRunner::STATUS_ERROR;
    }

    
/**
     * Runs the test case and collects the results in a TestResult object.
     * If no TestResult object is passed a new one will be created.
     *
     * @throws SebastianBergmannCodeCoverageInvalidArgumentException
     * @throws SebastianBergmannCodeCoverageUnintentionallyCoveredCodeException
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     * @throws CodeCoverageException
     * @throws UtilException
     */
    
public function run(TestResult $result null): TestResult
    
{
        if (
$result === null) {
            
$result $this->createResult();
        }

        if (!
$this instanceof ErrorTestCase && !$this instanceof WarningTestCase) {
            
$this->setTestResultObject($result);
        }

        if (!
$this instanceof ErrorTestCase &&
            !
$this instanceof WarningTestCase &&
            !
$this instanceof SkippedTestCase &&
            !
$this->handleDependencies()) {
            return 
$result;
        }

        if (
$this->runInSeparateProcess()) {
            
$runEntireClass $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess;

            try {
                
$class = new ReflectionClass($this);
                
// @codeCoverageIgnoreStart
            
} catch (ReflectionException $e) {
                throw new 
Exception(
                    
$e->getMessage(),
                    
$e->getCode(),
                    
$e
                
);
            }
            
// @codeCoverageIgnoreEnd

            
if ($runEntireClass) {
                
$template = new Template(
                    
__DIR__ '/../Util/PHP/Template/TestCaseClass.tpl'
                
);
            } else {
                
$template = new Template(
                    
__DIR__ '/../Util/PHP/Template/TestCaseMethod.tpl'
                
);
            }

            if (
$this->preserveGlobalState) {
                
$constants     GlobalState::getConstantsAsString();
                
$globals       GlobalState::getGlobalsAsString();
                
$includedFiles GlobalState::getIncludedFilesAsString();
                
$iniSettings   GlobalState::getIniSettingsAsString();
            } else {
                
$constants '';

                if (!empty(
$GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
                    
$globals '$GLOBALS['__PHPUNIT_BOOTSTRAP'] = ' var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";n";
                } else {
                    
$globals '';
                }

                
$includedFiles '';
                
$iniSettings   '';
            }

            
$coverage                                   $result->getCollectCodeCoverageInformation() ? 'true' 'false';
            
$isStrictAboutTestsThatDoNotTestAnything    $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' 'false';
            
$isStrictAboutOutputDuringTests             $result->isStrictAboutOutputDuringTests() ? 'true' 'false';
            
$enforcesTimeLimit                          $result->enforcesTimeLimit() ? 'true' 'false';
            
$isStrictAboutTodoAnnotatedTests            $result->isStrictAboutTodoAnnotatedTests() ? 'true' 'false';
            
$isStrictAboutResourceUsageDuringSmallTests $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' 'false';

            if (
defined('PHPUNIT_COMPOSER_INSTALL')) {
                
$composerAutoload var_export(PHPUNIT_COMPOSER_INSTALLtrue);
            } else {
                
$composerAutoload '''';
            }

            if (
defined('__PHPUNIT_PHAR__')) {
                
$phar var_export(__PHPUNIT_PHAR__true);
            } else {
                
$phar '''';
            }

            
$codeCoverage               $result->getCodeCoverage();
            
$codeCoverageFilter         null;
            
$cachesStaticAnalysis       'false';
            
$codeCoverageCacheDirectory null;
            
$driverMethod               'forLineCoverage';

            if (
$codeCoverage) {
                
$codeCoverageFilter $codeCoverage->filter();

                if (
$codeCoverage->collectsBranchAndPathCoverage()) {
                    
$driverMethod 'forLineAndPathCoverage';
                }

                if (
$codeCoverage->cachesStaticAnalysis()) {
                    
$cachesStaticAnalysis       'true';
                    
$codeCoverageCacheDirectory $codeCoverage->cacheDirectory();
                }
            }

            
$data                       var_export(serialize($this->data), true);
            
$dataName                   var_export($this->dataNametrue);
            
$dependencyInput            var_export(serialize($this->dependencyInput), true);
            
$includePath                var_export(get_include_path(), true);
            
$codeCoverageFilter         var_export(serialize($codeCoverageFilter), true);
            
$codeCoverageCacheDirectory var_export(serialize($codeCoverageCacheDirectory), true);
            
// must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
            // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
            
$data                       "'." $data ".'";
            
$dataName                   "'.(" $dataName ").'";
            
$dependencyInput            "'." $dependencyInput ".'";
            
$includePath                "'." $includePath ".'";
            
$codeCoverageFilter         "'." $codeCoverageFilter ".'";
            
$codeCoverageCacheDirectory "'." $codeCoverageCacheDirectory ".'";

            
$configurationFilePath $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';

            
$var = [
                
'composerAutoload'                           => $composerAutoload,
                
'phar'                                       => $phar,
                
'filename'                                   => $class->getFileName(),
                
'className'                                  => $class->getName(),
                
'collectCodeCoverageInformation'             => $coverage,
                
'cachesStaticAnalysis'                       => $cachesStaticAnalysis,
                
'codeCoverageCacheDirectory'                 => $codeCoverageCacheDirectory,
                
'driverMethod'                               => $driverMethod,
                
'data'                                       => $data,
                
'dataName'                                   => $dataName,
                
'dependencyInput'                            => $dependencyInput,
                
'constants'                                  => $constants,
                
'globals'                                    => $globals,
                
'include_path'                               => $includePath,
                
'included_files'                             => $includedFiles,
                
'iniSettings'                                => $iniSettings,
                
'isStrictAboutTestsThatDoNotTestAnything'    => $isStrictAboutTestsThatDoNotTestAnything,
                
'isStrictAboutOutputDuringTests'             => $isStrictAboutOutputDuringTests,
                
'enforcesTimeLimit'                          => $enforcesTimeLimit,
                
'isStrictAboutTodoAnnotatedTests'            => $isStrictAboutTodoAnnotatedTests,
                
'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests,
                
'codeCoverageFilter'                         => $codeCoverageFilter,
                
'configurationFilePath'                      => $configurationFilePath,
                
'name'                                       => $this->getName(false),
            ];

            if (!
$runEntireClass) {
                
$var['methodName'] = $this->name;
            }

            
$template->setVar($var);

            
$php AbstractPhpProcess::factory();
            
$php->runTestJob($template->render(), $this$result);
        } else {
            
$result->run($this);
        }

        
$this->result null;

        return 
$result;
    }

    
/**
     * Returns a builder object to create mock objects using a fluent interface.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $className
     *
     * @psalm-return MockBuilder<RealInstanceType>
     */
    
public function getMockBuilder(string $className): MockBuilder
    
{
        
$this->recordDoubledType($className);

        return new 
MockBuilder($this$className);
    }

    public function 
registerComparator(Comparator $comparator): void
    
{
        
ComparatorFactory::getInstance()->register($comparator);

        
$this->customComparators[] = $comparator;
    }

    
/**
     * @return string[]
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function doubledTypes(): array
    {
        return 
array_unique($this->doubledTypes);
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getGroups(): array
    {
        return 
$this->groups;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setGroups(array $groups): void
    
{
        
$this->groups $groups;
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getName(bool $withDataSet true): string
    
{
        if (
$withDataSet) {
            return 
$this->name $this->getDataSetAsString(false);
        }

        return 
$this->name;
    }

    
/**
     * Returns the size of the test.
     *
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getSize(): int
    
{
        return 
TestUtil::getSize(
            static::class,
            
$this->getName(false)
        );
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function hasSize(): bool
    
{
        return 
$this->getSize() !== TestUtil::UNKNOWN;
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function isSmall(): bool
    
{
        return 
$this->getSize() === TestUtil::SMALL;
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function isMedium(): bool
    
{
        return 
$this->getSize() === TestUtil::MEDIUM;
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function isLarge(): bool
    
{
        return 
$this->getSize() === TestUtil::LARGE;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getActualOutput(): string
    
{
        if (!
$this->outputBufferingActive) {
            return 
$this->output;
        }

        return (string) 
ob_get_contents();
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function hasOutput(): bool
    
{
        if (
$this->output === '') {
            return 
false;
        }

        if (
$this->hasExpectationOnOutput()) {
            return 
false;
        }

        return 
true;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function doesNotPerformAssertions(): bool
    
{
        return 
$this->doesNotPerformAssertions;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function hasExpectationOnOutput(): bool
    
{
        return 
is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex) || $this->outputRetrievedForAssertion;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getExpectedException(): ?string
    
{
        return 
$this->expectedException;
    }

    
/**
     * @return null|int|string
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getExpectedExceptionCode()
    {
        return 
$this->expectedExceptionCode;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getExpectedExceptionMessage(): ?string
    
{
        return 
$this->expectedExceptionMessage;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getExpectedExceptionMessageRegExp(): ?string
    
{
        return 
$this->expectedExceptionMessageRegExp;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void
    
{
        
$this->registerMockObjectsFromTestArgumentsRecursively $flag;
    }

    
/**
     * @throws Throwable
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function runBare(): void
    
{
        
$this->numAssertions 0;

        
$this->snapshotGlobalState();
        
$this->startOutputBuffering();
        
clearstatcache();
        
$currentWorkingDirectory getcwd();

        
$hookMethods TestUtil::getHookMethods(static::class);

        
$hasMetRequirements false;

        try {
            
$this->checkRequirements();
            
$hasMetRequirements true;

            if (
$this->inIsolation) {
                foreach (
$hookMethods['beforeClass'] as $method) {
                    
$this->{$method}();
                }
            }

            
$this->setDoesNotPerformAssertionsFromAnnotation();

            foreach (
$hookMethods['before'] as $method) {
                
$this->{$method}();
            }

            foreach (
$hookMethods['preCondition'] as $method) {
                
$this->{$method}();
            }

            
$this->testResult $this->runTest();
            
$this->verifyMockObjects();

            foreach (
$hookMethods['postCondition'] as $method) {
                
$this->{$method}();
            }

            if (!empty(
$this->warnings)) {
                throw new 
Warning(
                    
implode(
                        
"n",
                        
array_unique($this->warnings)
                    )
                );
            }

            
$this->status BaseTestRunner::STATUS_PASSED;
        } catch (
IncompleteTest $e) {
            
$this->status        BaseTestRunner::STATUS_INCOMPLETE;
            
$this->statusMessage $e->getMessage();
        } catch (
SkippedTest $e) {
            
$this->status        BaseTestRunner::STATUS_SKIPPED;
            
$this->statusMessage $e->getMessage();
        } catch (
Warning $e) {
            
$this->status        BaseTestRunner::STATUS_WARNING;
            
$this->statusMessage $e->getMessage();
        } catch (
AssertionFailedError $e) {
            
$this->status        BaseTestRunner::STATUS_FAILURE;
            
$this->statusMessage $e->getMessage();
        } catch (
PredictionException $e) {
            
$this->status        BaseTestRunner::STATUS_FAILURE;
            
$this->statusMessage $e->getMessage();
        } catch (
Throwable $_e) {
            
$e                   $_e;
            
$this->status        BaseTestRunner::STATUS_ERROR;
            
$this->statusMessage $_e->getMessage();
        }

        
$this->mockObjects = [];
        
$this->prophet     null;

        
// Tear down the fixture. An exception raised in tearDown() will be
        // caught and passed on when no exception was raised before.
        
try {
            if (
$hasMetRequirements) {
                foreach (
$hookMethods['after'] as $method) {
                    
$this->{$method}();
                }

                if (
$this->inIsolation) {
                    foreach (
$hookMethods['afterClass'] as $method) {
                        
$this->{$method}();
                    }
                }
            }
        } catch (
Throwable $_e) {
            
$e $e ?? $_e;
        }

        try {
            
$this->stopOutputBuffering();
        } catch (
RiskyTestError $_e) {
            
$e $e ?? $_e;
        }

        if (isset(
$_e)) {
            
$this->status        BaseTestRunner::STATUS_ERROR;
            
$this->statusMessage $_e->getMessage();
        }

        
clearstatcache();

        if (
$currentWorkingDirectory !== getcwd()) {
            
chdir($currentWorkingDirectory);
        }

        
$this->restoreGlobalState();
        
$this->unregisterCustomComparators();
        
$this->cleanupIniSettings();
        
$this->cleanupLocaleSettings();
        
libxml_clear_errors();

        
// Perform assertion on output.
        
if (!isset($e)) {
            try {
                if (
$this->outputExpectedRegex !== null) {
                    
$this->assertMatchesRegularExpression($this->outputExpectedRegex$this->output);
                } elseif (
$this->outputExpectedString !== null) {
                    
$this->assertEquals($this->outputExpectedString$this->output);
                }
            } catch (
Throwable $_e) {
                
$e $_e;
            }
        }

        
// Workaround for missing "finally".
        
if (isset($e)) {
            if (
$e instanceof PredictionException) {
                
$e = new AssertionFailedError($e->getMessage());
            }

            
$this->onNotSuccessfulTest($e);
        }
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setName(string $name): void
    
{
        
$this->name $name;

        if (
is_callable($this->sortId(), true)) {
            
$this->providedTests = [new ExecutionOrderDependency($this->sortId())];
        }
    }

    
/**
     * @param list<ExecutionOrderDependency> $dependencies
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setDependencies(array $dependencies): void
    
{
        
$this->dependencies $dependencies;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setDependencyInput(array $dependencyInput): void
    
{
        
$this->dependencyInput $dependencyInput;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setBeStrictAboutChangesToGlobalState(?bool $beStrictAboutChangesToGlobalState): void
    
{
        
$this->beStrictAboutChangesToGlobalState $beStrictAboutChangesToGlobalState;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setBackupGlobals(?bool $backupGlobals): void
    
{
        if (
$this->backupGlobals === null && $backupGlobals !== null) {
            
$this->backupGlobals $backupGlobals;
        }
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setBackupStaticAttributes(?bool $backupStaticAttributes): void
    
{
        if (
$this->backupStaticAttributes === null && $backupStaticAttributes !== null) {
            
$this->backupStaticAttributes $backupStaticAttributes;
        }
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void
    
{
        if (
$this->runTestInSeparateProcess === null) {
            
$this->runTestInSeparateProcess $runTestInSeparateProcess;
        }
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void
    
{
        if (
$this->runClassInSeparateProcess === null) {
            
$this->runClassInSeparateProcess $runClassInSeparateProcess;
        }
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setPreserveGlobalState(bool $preserveGlobalState): void
    
{
        
$this->preserveGlobalState $preserveGlobalState;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setInIsolation(bool $inIsolation): void
    
{
        
$this->inIsolation $inIsolation;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function isInIsolation(): bool
    
{
        return 
$this->inIsolation;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getResult()
    {
        return 
$this->testResult;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setResult($result): void
    
{
        
$this->testResult $result;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setOutputCallback(callable $callback): void
    
{
        
$this->outputCallback $callback;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getTestResultObject(): ?TestResult
    
{
        return 
$this->result;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function setTestResultObject(TestResult $result): void
    
{
        
$this->result $result;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function registerMockObject(MockObject $mockObject): void
    
{
        
$this->mockObjects[] = $mockObject;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function addToAssertionCount(int $count): void
    
{
        
$this->numAssertions += $count;
    }

    
/**
     * Returns the number of assertions performed by this test.
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getNumAssertions(): int
    
{
        return 
$this->numAssertions;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function usesDataProvider(): bool
    
{
        return !empty(
$this->data);
    }

    
/**
     * @return int|string
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function dataName()
    {
        return 
$this->dataName;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getDataSetAsString(bool $includeData true): string
    
{
        
$buffer '';

        if (!empty(
$this->data)) {
            if (
is_int($this->dataName)) {
                
$buffer .= sprintf(' with data set #%d'$this->dataName);
            } else {
                
$buffer .= sprintf(' with data set "%s"'$this->dataName);
            }

            if (
$includeData) {
                
$exporter = new Exporter;

                
$buffer .= sprintf(' (%s)'$exporter->shortenedRecursiveExport($this->data));
            }
        }

        return 
$buffer;
    }

    
/**
     * Gets the data set of a TestCase.
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function getProvidedData(): array
    {
        return 
$this->data;
    }

    
/**
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
public function addWarning(string $warning): void
    
{
        
$this->warnings[] = $warning;
    }

    public function 
sortId(): string
    
{
        
$id $this->name;

        if (
strpos($id'::') === false) {
            
$id = static::class . '::' $id;
        }

        if (
$this->usesDataProvider()) {
            
$id .= $this->getDataSetAsString(false);
        }

        return 
$id;
    }

    
/**
     * Returns the normalized test name as class::method.
     *
     * @return list<ExecutionOrderDependency>
     */
    
public function provides(): array
    {
        return 
$this->providedTests;
    }

    
/**
     * Returns a list of normalized dependency names, class::method.
     *
     * This list can differ from the raw dependencies as the resolver has
     * no need for the [!][shallow]clone prefix that is filtered out
     * during normalization.
     *
     * @return list<ExecutionOrderDependency>
     */
    
public function requires(): array
    {
        return 
$this->dependencies;
    }

    
/**
     * Override to run the test and assert its state.
     *
     * @throws SebastianBergmannObjectEnumeratorInvalidArgumentException
     * @throws AssertionFailedError
     * @throws Exception
     * @throws ExpectationFailedException
     * @throws Throwable
     */
    
protected function runTest()
    {
        if (
trim($this->name) === '') {
            throw new 
Exception(
                
'PHPUnitFrameworkTestCase::$name must be a non-blank string.'
            
);
        }

        
$testArguments array_merge($this->data$this->dependencyInput);

        
$this->registerMockObjectsFromTestArguments($testArguments);

        try {
            
$testResult $this->{$this->name}(...array_values($testArguments));
        } catch (
Throwable $exception) {
            if (!
$this->checkExceptionExpectations($exception)) {
                throw 
$exception;
            }

            if (
$this->expectedException !== null) {
                if (
$this->expectedException === Error::class) {
                    
$this->assertThat(
                        
$exception,
                        
LogicalOr::fromConstraints(
                            new 
ExceptionConstraint(Error::class),
                            new 
ExceptionConstraint(Error::class)
                        )
                    );
                } else {
                    
$this->assertThat(
                        
$exception,
                        new 
ExceptionConstraint(
                            
$this->expectedException
                        
)
                    );
                }
            }

            if (
$this->expectedExceptionMessage !== null) {
                
$this->assertThat(
                    
$exception,
                    new 
ExceptionMessage(
                        
$this->expectedExceptionMessage
                    
)
                );
            }

            if (
$this->expectedExceptionMessageRegExp !== null) {
                
$this->assertThat(
                    
$exception,
                    new 
ExceptionMessageRegularExpression(
                        
$this->expectedExceptionMessageRegExp
                    
)
                );
            }

            if (
$this->expectedExceptionCode !== null) {
                
$this->assertThat(
                    
$exception,
                    new 
ExceptionCode(
                        
$this->expectedExceptionCode
                    
)
                );
            }

            return;
        }

        if (
$this->expectedException !== null) {
            
$this->assertThat(
                
null,
                new 
ExceptionConstraint(
                    
$this->expectedException
                
)
            );
        } elseif (
$this->expectedExceptionMessage !== null) {
            
$this->numAssertions++;

            throw new 
AssertionFailedError(
                
sprintf(
                    
'Failed asserting that exception with message "%s" is thrown',
                    
$this->expectedExceptionMessage
                
)
            );
        } elseif (
$this->expectedExceptionMessageRegExp !== null) {
            
$this->numAssertions++;

            throw new 
AssertionFailedError(
                
sprintf(
                    
'Failed asserting that exception with message matching "%s" is thrown',
                    
$this->expectedExceptionMessageRegExp
                
)
            );
        } elseif (
$this->expectedExceptionCode !== null) {
            
$this->numAssertions++;

            throw new 
AssertionFailedError(
                
sprintf(
                    
'Failed asserting that exception with code "%s" is thrown',
                    
$this->expectedExceptionCode
                
)
            );
        }

        return 
$testResult;
    }

    
/**
     * This method is a wrapper for the ini_set() function that automatically
     * resets the modified php.ini setting to its original value after the
     * test is run.
     *
     * @throws Exception
     */
    
protected function iniSet(string $varNamestring $newValue): void
    
{
        
$currentValue ini_set($varName$newValue);

        if (
$currentValue !== false) {
            
$this->iniSettings[$varName] = $currentValue;
        } else {
            throw new 
Exception(
                
sprintf(
                    
'INI setting "%s" could not be set to "%s".',
                    
$varName,
                    
$newValue
                
)
            );
        }
    }

    
/**
     * This method is a wrapper for the setlocale() function that automatically
     * resets the locale to its original value after the test is run.
     *
     * @throws Exception
     */
    
protected function setLocale(...$args): void
    
{
        if (
count($args) < 2) {
            throw new 
Exception;
        }

        [
$category$locale] = $args;

        if (!
in_array($categoryself::LOCALE_CATEGORIEStrue)) {
            throw new 
Exception;
        }

        if (!
is_array($locale) && !is_string($locale)) {
            throw new 
Exception;
        }

        
$this->locale[$category] = setlocale($category0);

        
$result setlocale(...$args);

        if (
$result === false) {
            throw new 
Exception(
                
'The locale functionality is not implemented on your platform, ' .
                
'the specified locale does not exist or the category name is ' .
                
'invalid.'
            
);
        }
    }

    
/**
     * Makes configurable stub for the specified class.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param    class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return   Stub&RealInstanceType
     */
    
protected function createStub(string $originalClassName): Stub
    
{
        return 
$this->createMockObject($originalClassName);
    }

    
/**
     * Returns a mock object for the specified class.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function createMock(string $originalClassName): MockObject
    
{
        return 
$this->createMockObject($originalClassName);
    }

    
/**
     * Returns a configured mock object for the specified class.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function createConfiguredMock(string $originalClassName, array $configuration): MockObject
    
{
        
$o $this->createMockObject($originalClassName);

        foreach (
$configuration as $method => $return) {
            
$o->method($method)->willReturn($return);
        }

        return 
$o;
    }

    
/**
     * Returns a partial mock object for the specified class.
     *
     * @param string[] $methods
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function createPartialMock(string $originalClassName, array $methods): MockObject
    
{
        try {
            
$reflector = new ReflectionClass($originalClassName);
            
// @codeCoverageIgnoreStart
        
} catch (ReflectionException $e) {
            throw new 
Exception(
                
$e->getMessage(),
                
$e->getCode(),
                
$e
            
);
        }
        
// @codeCoverageIgnoreEnd

        
$mockedMethodsThatDontExist array_filter(
            
$methods,
            static function (
string $method) use ($reflector)
            {
                return !
$reflector->hasMethod($method);
            }
        );

        if (
$mockedMethodsThatDontExist) {
            
$this->addWarning(
                
sprintf(
                    
'createPartialMock() called with method(s) %s that do not exist in %s. This will not be allowed in future versions of PHPUnit.',
                    
implode(', '$mockedMethodsThatDontExist),
                    
$originalClassName
                
)
            );
        }

        return 
$this->getMockBuilder($originalClassName)
                    ->
disableOriginalConstructor()
                    ->
disableOriginalClone()
                    ->
disableArgumentCloning()
                    ->
disallowMockingUnknownTypes()
                    ->
setMethods(empty($methods) ? null $methods)
                    ->
getMock();
    }

    
/**
     * Returns a test proxy for the specified class.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject
    
{
        return 
$this->getMockBuilder($originalClassName)
                    ->
setConstructorArgs($constructorArguments)
                    ->
enableProxyingToOriginalMethods()
                    ->
getMock();
    }

    
/**
     * Mocks the specified class and returns the name of the mocked class.
     *
     * @param null|array $methods $methods
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType>|string $originalClassName
     *
     * @psalm-return class-string<MockObject&RealInstanceType>
     */
    
protected function getMockClass(string $originalClassName$methods = [], array $arguments = [], string $mockClassName ''bool $callOriginalConstructor falsebool $callOriginalClone truebool $callAutoload truebool $cloneArguments false): string
    
{
        
$this->recordDoubledType($originalClassName);

        
$mock $this->getMockObjectGenerator()->getMock(
            
$originalClassName,
            
$methods,
            
$arguments,
            
$mockClassName,
            
$callOriginalConstructor,
            
$callOriginalClone,
            
$callAutoload,
            
$cloneArguments
        
);

        return 
get_class($mock);
    }

    
/**
     * Returns a mock object for the specified abstract class with all abstract
     * methods of the class mocked. Concrete methods are not mocked by default.
     * To mock concrete methods, use the 7th parameter ($mockedMethods).
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName ''bool $callOriginalConstructor truebool $callOriginalClone truebool $callAutoload true, array $mockedMethods = [], bool $cloneArguments false): MockObject
    
{
        
$this->recordDoubledType($originalClassName);

        
$mockObject $this->getMockObjectGenerator()->getMockForAbstractClass(
            
$originalClassName,
            
$arguments,
            
$mockClassName,
            
$callOriginalConstructor,
            
$callOriginalClone,
            
$callAutoload,
            
$mockedMethods,
            
$cloneArguments
        
);

        
$this->registerMockObject($mockObject);

        return 
$mockObject;
    }

    
/**
     * Returns a mock object based on the given WSDL file.
     *
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType>|string $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
protected function getMockFromWsdl(string $wsdlFilestring $originalClassName ''string $mockClassName '', array $methods = [], bool $callOriginalConstructor true, array $options = []): MockObject
    
{
        
$this->recordDoubledType(SoapClient::class);

        if (
$originalClassName === '') {
            
$fileName          pathinfo(basename(parse_url($wsdlFilePHP_URL_PATH)), PATHINFO_FILENAME);
            
$originalClassName preg_replace('/W/'''$fileName);
        }

        if (!
class_exists($originalClassName)) {
            eval(
                
$this->getMockObjectGenerator()->generateClassFromWsdl(
                    
$wsdlFile,
                    
$originalClassName,
                    
$methods,
                    
$options
                
)
            );
        }

        
$mockObject $this->getMockObjectGenerator()->getMock(
            
$originalClassName,
            
$methods,
            [
''$options],
            
$mockClassName,
            
$callOriginalConstructor,
            
false,
            
false
        
);

        
$this->registerMockObject($mockObject);

        return 
$mockObject;
    }

    
/**
     * Returns a mock object for the specified trait with all abstract methods
     * of the trait mocked. Concrete methods to mock can be specified with the
     * `$mockedMethods` parameter.
     *
     * @psalm-param trait-string $traitName
     */
    
protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName ''bool $callOriginalConstructor truebool $callOriginalClone truebool $callAutoload true, array $mockedMethods = [], bool $cloneArguments false): MockObject
    
{
        
$this->recordDoubledType($traitName);

        
$mockObject $this->getMockObjectGenerator()->getMockForTrait(
            
$traitName,
            
$arguments,
            
$mockClassName,
            
$callOriginalConstructor,
            
$callOriginalClone,
            
$callAutoload,
            
$mockedMethods,
            
$cloneArguments
        
);

        
$this->registerMockObject($mockObject);

        return 
$mockObject;
    }

    
/**
     * Returns an object for the specified trait.
     *
     * @psalm-param trait-string $traitName
     */
    
protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName ''bool $callOriginalConstructor truebool $callOriginalClone truebool $callAutoload true): object
    
{
        
$this->recordDoubledType($traitName);

        return 
$this->getMockObjectGenerator()->getObjectForTrait(
            
$traitName,
            
$traitClassName,
            
$callAutoload,
            
$callOriginalConstructor,
            
$arguments
        
);
    }

    
/**
     * @throws ProphecyExceptionDoublerClassNotFoundException
     * @throws ProphecyExceptionDoublerDoubleException
     * @throws ProphecyExceptionDoublerInterfaceNotFoundException
     *
     * @psalm-param class-string|null $classOrInterface
     *
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4141
     */
    
protected function prophesize(?string $classOrInterface null): ObjectProphecy
    
{
        if (!
class_exists(Prophet::class)) {
            throw new 
Exception('This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".');
        }

        
$this->addWarning('PHPUnitFrameworkTestCase::prophesize() is deprecated and will be removed in PHPUnit 10. Please use the trait provided by phpspec/prophecy-phpunit.');

        if (
is_string($classOrInterface)) {
            
$this->recordDoubledType($classOrInterface);
        }

        return 
$this->getProphet()->prophesize($classOrInterface);
    }

    
/**
     * Creates a default TestResult object.
     *
     * @internal This method is not covered by the backward compatibility promise for PHPUnit
     */
    
protected function createResult(): TestResult
    
{
        return new 
TestResult;
    }

    
/**
     * This method is called when a test method did not execute successfully.
     *
     * @throws Throwable
     */
    
protected function onNotSuccessfulTest(Throwable $t): void
    
{
        throw 
$t;
    }

    protected function 
recordDoubledType(string $originalClassName): void
    
{
        
$this->doubledTypes[] = $originalClassName;
    }

    
/**
     * @throws Throwable
     */
    
private function verifyMockObjects(): void
    
{
        foreach (
$this->mockObjects as $mockObject) {
            if (
$mockObject->__phpunit_hasMatchers()) {
                
$this->numAssertions++;
            }

            
$mockObject->__phpunit_verify(
                
$this->shouldInvocationMockerBeReset($mockObject)
            );
        }

        if (
$this->prophet !== null) {
            try {
                
$this->prophet->checkPredictions();
            } finally {
                foreach (
$this->prophet->getProphecies() as $objectProphecy) {
                    foreach (
$objectProphecy->getMethodProphecies() as $methodProphecies) {
                        foreach (
$methodProphecies as $methodProphecy) {
                            
/* @var MethodProphecy $methodProphecy */
                            
$this->numAssertions += count($methodProphecy->getCheckedPredictions());
                        }
                    }
                }
            }
        }
    }

    
/**
     * @throws SkippedTestError
     * @throws SyntheticSkippedError
     * @throws Warning
     */
    
private function checkRequirements(): void
    
{
        if (!
$this->name || !method_exists($this$this->name)) {
            return;
        }

        
$missingRequirements TestUtil::getMissingRequirements(
            static::class,
            
$this->name
        
);

        if (!empty(
$missingRequirements)) {
            
$this->markTestSkipped(implode(PHP_EOL$missingRequirements));
        }
    }

    private function 
handleDependencies(): bool
    
{
        if ([] === 
$this->dependencies || $this->inIsolation) {
            return 
true;
        }

        
$passed     $this->result->passed();
        
$passedKeys array_keys($passed);
        
$numKeys    count($passedKeys);

        for (
$i 0$i $numKeys$i++) {
            
$pos strpos($passedKeys[$i], ' with data set');

            if (
$pos !== false) {
                
$passedKeys[$i] = substr($passedKeys[$i], 0$pos);
            }
        }

        
$passedKeys array_flip(array_unique($passedKeys));

        foreach (
$this->dependencies as $dependency) {
            if (!
$dependency->isValid()) {
                
$this->markSkippedForNotSpecifyingDependency();

                return 
false;
            }

            if (
$dependency->targetIsClass()) {
                
$dependencyClassName $dependency->getTargetClassName();

                if (
array_search($dependencyClassName$this->result->passedClasses(), true) === false) {
                    
$this->markSkippedForMissingDependency($dependency);

                    return 
false;
                }

                continue;
            }

            
$dependencyTarget $dependency->getTarget();

            if (!isset(
$passedKeys[$dependencyTarget])) {
                if (!
$this->isCallableTestMethod($dependencyTarget)) {
                    
$this->markWarningForUncallableDependency($dependency);
                } else {
                    
$this->markSkippedForMissingDependency($dependency);
                }

                return 
false;
            }

            if (isset(
$passed[$dependencyTarget])) {
                if (
$passed[$dependencyTarget]['size'] != PHPUnitUtilTest::UNKNOWN &&
                    
$this->getSize() != PHPUnitUtilTest::UNKNOWN &&
                    
$passed[$dependencyTarget]['size'] > $this->getSize()) {
                    
$this->result->addError(
                        
$this,
                        new 
SkippedTestError(
                            
'This test depends on a test that is larger than itself.'
                        
),
                        
0
                    
);

                    return 
false;
                }

                if (
$dependency->useDeepClone()) {
                    
$deepCopy = new DeepCopy;
                    
$deepCopy->skipUncloneable(false);

                    
$this->dependencyInput[$dependencyTarget] = $deepCopy->copy($passed[$dependencyTarget]['result']);
                } elseif (
$dependency->useShallowClone()) {
                    
$this->dependencyInput[$dependencyTarget] = clone $passed[$dependencyTarget]['result'];
                } else {
                    
$this->dependencyInput[$dependencyTarget] = $passed[$dependencyTarget]['result'];
                }
            } else {
                
$this->dependencyInput[$dependencyTarget] = null;
            }
        }

        return 
true;
    }

    private function 
markSkippedForNotSpecifyingDependency(): void
    
{
        
$this->status BaseTestRunner::STATUS_SKIPPED;

        
$this->result->startTest($this);

        
$this->result->addError(
            
$this,
            new 
SkippedTestError(
                
'This method has an invalid @depends annotation.'
            
),
            
0
        
);

        
$this->result->endTest($this0);
    }

    private function 
markSkippedForMissingDependency(ExecutionOrderDependency $dependency): void
    
{
        
$this->status BaseTestRunner::STATUS_SKIPPED;

        
$this->result->startTest($this);

        
$this->result->addError(
            
$this,
            new 
SkippedTestError(
                
sprintf(
                    
'This test depends on "%s" to pass.',
                    
$dependency->getTarget()
                )
            ),
            
0
        
);

        
$this->result->endTest($this0);
    }

    private function 
markWarningForUncallableDependency(ExecutionOrderDependency $dependency): void
    
{
        
$this->status BaseTestRunner::STATUS_WARNING;

        
$this->result->startTest($this);

        
$this->result->addWarning(
            
$this,
            new 
Warning(
                
sprintf(
                    
'This test depends on "%s" which does not exist.',
                    
$dependency->getTarget()
                )
            ),
            
0
        
);

        
$this->result->endTest($this0);
    }

    
/**
     * Get the mock object generator, creating it if it doesn't exist.
     */
    
private function getMockObjectGenerator(): MockGenerator
    
{
        if (
$this->mockObjectGenerator === null) {
            
$this->mockObjectGenerator = new MockGenerator;
        }

        return 
$this->mockObjectGenerator;
    }

    private function 
startOutputBuffering(): void
    
{
        
ob_start();

        
$this->outputBufferingActive true;
        
$this->outputBufferingLevel  ob_get_level();
    }

    
/**
     * @throws RiskyTestError
     */
    
private function stopOutputBuffering(): void
    
{
        if (
ob_get_level() !== $this->outputBufferingLevel) {
            while (
ob_get_level() >= $this->outputBufferingLevel) {
                
ob_end_clean();
            }

            throw new 
RiskyTestError(
                
'Test code or tested code did not (only) close its own output buffers'
            
);
        }

        
$this->output ob_get_contents();

        if (
$this->outputCallback !== false) {
            
$this->output = (string) call_user_func($this->outputCallback$this->output);
        }

        
ob_end_clean();

        
$this->outputBufferingActive false;
        
$this->outputBufferingLevel  ob_get_level();
    }

    private function 
snapshotGlobalState(): void
    
{
        if (
$this->runTestInSeparateProcess || $this->inIsolation ||
            (!
$this->backupGlobals && !$this->backupStaticAttributes)) {
            return;
        }

        
$this->snapshot $this->createGlobalStateSnapshot($this->backupGlobals === true);
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     * @throws RiskyTestError
     */
    
private function restoreGlobalState(): void
    
{
        if (!
$this->snapshot instanceof Snapshot) {
            return;
        }

        if (
$this->beStrictAboutChangesToGlobalState) {
            try {
                
$this->compareGlobalStateSnapshots(
                    
$this->snapshot,
                    
$this->createGlobalStateSnapshot($this->backupGlobals === true)
                );
            } catch (
RiskyTestError $rte) {
                
// Intentionally left empty
            
}
        }

        
$restorer = new Restorer;

        if (
$this->backupGlobals) {
            
$restorer->restoreGlobalVariables($this->snapshot);
        }

        if (
$this->backupStaticAttributes) {
            
$restorer->restoreStaticAttributes($this->snapshot);
        }

        
$this->snapshot null;

        if (isset(
$rte)) {
            throw 
$rte;
        }
    }

    private function 
createGlobalStateSnapshot(bool $backupGlobals): Snapshot
    
{
        
$excludeList = new ExcludeList;

        foreach (
$this->backupGlobalsExcludeList as $globalVariable) {
            
$excludeList->addGlobalVariable($globalVariable);
        }

        if (!empty(
$this->backupGlobalsBlacklist)) {
            
$this->addWarning('PHPUnitFrameworkTestCase::$backupGlobalsBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnitFrameworkTestCase::$backupGlobalsExcludeList instead.');

            foreach (
$this->backupGlobalsBlacklist as $globalVariable) {
                
$excludeList->addGlobalVariable($globalVariable);
            }
        }

        if (!
defined('PHPUNIT_TESTSUITE')) {
            
$excludeList->addClassNamePrefix('PHPUnit');
            
$excludeList->addClassNamePrefix('SebastianBergmannCodeCoverage');
            
$excludeList->addClassNamePrefix('SebastianBergmannFileIterator');
            
$excludeList->addClassNamePrefix('SebastianBergmannInvoker');
            
$excludeList->addClassNamePrefix('SebastianBergmannTemplate');
            
$excludeList->addClassNamePrefix('SebastianBergmannTimer');
            
$excludeList->addClassNamePrefix('DoctrineInstantiator');
            
$excludeList->addClassNamePrefix('Prophecy');
            
$excludeList->addStaticAttribute(ComparatorFactory::class, 'instance');

            foreach (
$this->backupStaticAttributesExcludeList as $class => $attributes) {
                foreach (
$attributes as $attribute) {
                    
$excludeList->addStaticAttribute($class$attribute);
                }
            }

            if (!empty(
$this->backupStaticAttributesBlacklist)) {
                
$this->addWarning('PHPUnitFrameworkTestCase::$backupStaticAttributesBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnitFrameworkTestCase::$backupStaticAttributesExcludeList instead.');

                foreach (
$this->backupStaticAttributesBlacklist as $class => $attributes) {
                    foreach (
$attributes as $attribute) {
                        
$excludeList->addStaticAttribute($class$attribute);
                    }
                }
            }
        }

        return new 
Snapshot(
            
$excludeList,
            
$backupGlobals,
            (bool) 
$this->backupStaticAttributes,
            
false,
            
false,
            
false,
            
false,
            
false,
            
false,
            
false
        
);
    }

    
/**
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     * @throws RiskyTestError
     */
    
private function compareGlobalStateSnapshots(Snapshot $beforeSnapshot $after): void
    
{
        
$backupGlobals $this->backupGlobals === null || $this->backupGlobals;

        if (
$backupGlobals) {
            
$this->compareGlobalStateSnapshotPart(
                
$before->globalVariables(),
                
$after->globalVariables(),
                
"--- Global variables before the testn+++ Global variables after the testn"
            
);

            
$this->compareGlobalStateSnapshotPart(
                
$before->superGlobalVariables(),
                
$after->superGlobalVariables(),
                
"--- Super-global variables before the testn+++ Super-global variables after the testn"
            
);
        }

        if (
$this->backupStaticAttributes) {
            
$this->compareGlobalStateSnapshotPart(
                
$before->staticAttributes(),
                
$after->staticAttributes(),
                
"--- Static attributes before the testn+++ Static attributes after the testn"
            
);
        }
    }

    
/**
     * @throws RiskyTestError
     */
    
private function compareGlobalStateSnapshotPart(array $before, array $afterstring $header): void
    
{
        if (
$before != $after) {
            
$differ   = new Differ($header);
            
$exporter = new Exporter;

            
$diff $differ->diff(
                
$exporter->export($before),
                
$exporter->export($after)
            );

            throw new 
RiskyTestError(
                
$diff
            
);
        }
    }

    private function 
getProphet(): Prophet
    
{
        if (
$this->prophet === null) {
            
$this->prophet = new Prophet;
        }

        return 
$this->prophet;
    }

    
/**
     * @throws SebastianBergmannObjectEnumeratorInvalidArgumentException
     */
    
private function shouldInvocationMockerBeReset(MockObject $mock): bool
    
{
        
$enumerator = new Enumerator;

        foreach (
$enumerator->enumerate($this->dependencyInput) as $object) {
            if (
$mock === $object) {
                return 
false;
            }
        }

        if (!
is_array($this->testResult) && !is_object($this->testResult)) {
            return 
true;
        }

        return !
in_array($mock$enumerator->enumerate($this->testResult), true);
    }

    
/**
     * @throws SebastianBergmannObjectEnumeratorInvalidArgumentException
     * @throws SebastianBergmannObjectReflectorInvalidArgumentException
     * @throws SebastianBergmannRecursionContextInvalidArgumentException
     */
    
private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []): void
    
{
        if (
$this->registerMockObjectsFromTestArgumentsRecursively) {
            foreach ((new 
Enumerator)->enumerate($testArguments) as $object) {
                if (
$object instanceof MockObject) {
                    
$this->registerMockObject($object);
                }
            }
        } else {
            foreach (
$testArguments as $testArgument) {
                if (
$testArgument instanceof MockObject) {
                    
$testArgument Cloner::clone($testArgument);

                    
$this->registerMockObject($testArgument);
                } elseif (
is_array($testArgument) && !in_array($testArgument$visitedtrue)) {
                    
$visited[] = $testArgument;

                    
$this->registerMockObjectsFromTestArguments(
                        
$testArgument,
                        
$visited
                    
);
                }
            }
        }
    }

    private function 
setDoesNotPerformAssertionsFromAnnotation(): void
    
{
        
$annotations TestUtil::parseTestMethodAnnotations(
            static::class,
            
$this->name
        
);

        if (isset(
$annotations['method']['doesNotPerformAssertions'])) {
            
$this->doesNotPerformAssertions true;
        }
    }

    private function 
unregisterCustomComparators(): void
    
{
        
$factory ComparatorFactory::getInstance();

        foreach (
$this->customComparators as $comparator) {
            
$factory->unregister($comparator);
        }

        
$this->customComparators = [];
    }

    private function 
cleanupIniSettings(): void
    
{
        foreach (
$this->iniSettings as $varName => $oldValue) {
            
ini_set($varName$oldValue);
        }

        
$this->iniSettings = [];
    }

    private function 
cleanupLocaleSettings(): void
    
{
        foreach (
$this->locale as $category => $locale) {
            
setlocale($category$locale);
        }

        
$this->locale = [];
    }

    
/**
     * @throws Exception
     */
    
private function checkExceptionExpectations(Throwable $throwable): bool
    
{
        
$result false;

        if (
$this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) {
            
$result true;
        }

        if (
$throwable instanceof Exception) {
            
$result false;
        }

        if (
is_string($this->expectedException)) {
            try {
                
$reflector = new ReflectionClass($this->expectedException);
                
// @codeCoverageIgnoreStart
            
} catch (ReflectionException $e) {
                throw new 
Exception(
                    
$e->getMessage(),
                    
$e->getCode(),
                    
$e
                
);
            }
            
// @codeCoverageIgnoreEnd

            
if ($this->expectedException === 'PHPUnitFrameworkException' ||
                
$this->expectedException === 'PHPUnitFrameworkException' ||
                
$reflector->isSubclassOf(Exception::class)) {
                
$result true;
            }
        }

        return 
$result;
    }

    private function 
runInSeparateProcess(): bool
    
{
        return (
$this->runTestInSeparateProcess || $this->runClassInSeparateProcess) &&
            !
$this->inIsolation && !$this instanceof PhptTestCase;
    }

    private function 
isCallableTestMethod(string $dependency): bool
    
{
        [
$className$methodName] = explode('::'$dependency);

        if (!
class_exists($className)) {
            return 
false;
        }

        try {
            
$class = new ReflectionClass($className);
        } catch (
ReflectionException $e) {
            return 
false;
        }

        if (!
$class->isSubclassOf(__CLASS__)) {
            return 
false;
        }

        if (!
$class->hasMethod($methodName)) {
            return 
false;
        }

        try {
            
$method $class->getMethod($methodName);
        } catch (
ReflectionException $e) {
            return 
false;
        }

        return 
TestUtil::isTestMethod($method);
    }

    
/**
     * @psalm-template RealInstanceType of object
     *
     * @psalm-param class-string<RealInstanceType> $originalClassName
     *
     * @psalm-return MockObject&RealInstanceType
     */
    
private function createMockObject(string $originalClassName): MockObject
    
{
        return 
$this->getMockBuilder($originalClassName)
                    ->
disableOriginalConstructor()
                    ->
disableOriginalClone()
                    ->
disableArgumentCloning()
                    ->
disallowMockingUnknownTypes()
                    ->
getMock();
    }
}
Онлайн: 1
Реклама