1<?php 2/* 3 * This file is part of PHPUnit. 4 * 5 * (c) Sebastian Bergmann <sebastian@phpunit.de> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11use SebastianBergmann\GlobalState\Snapshot; 12use SebastianBergmann\GlobalState\Restorer; 13use SebastianBergmann\GlobalState\Blacklist; 14use SebastianBergmann\Diff\Differ; 15use SebastianBergmann\Exporter\Exporter; 16use SebastianBergmann\ObjectEnumerator\Enumerator; 17use Prophecy\Exception\Prediction\PredictionException; 18use Prophecy\Prophet; 19use DeepCopy\DeepCopy; 20 21/** 22 * A TestCase defines the fixture to run multiple tests. 23 * 24 * To define a TestCase 25 * 26 * 1) Implement a subclass of PHPUnit_Framework_TestCase. 27 * 2) Define instance variables that store the state of the fixture. 28 * 3) Initialize the fixture state by overriding setUp(). 29 * 4) Clean-up after a test by overriding tearDown(). 30 * 31 * Each test runs in its own fixture so there can be no side effects 32 * among test runs. 33 * 34 * Here is an example: 35 * 36 * <code> 37 * <?php 38 * class MathTest extends PHPUnit_Framework_TestCase 39 * { 40 * public $value1; 41 * public $value2; 42 * 43 * protected function setUp() 44 * { 45 * $this->value1 = 2; 46 * $this->value2 = 3; 47 * } 48 * } 49 * ?> 50 * </code> 51 * 52 * For each test implement a method which interacts with the fixture. 53 * Verify the expected results with assertions specified by calling 54 * assert with a boolean. 55 * 56 * <code> 57 * <?php 58 * public function testPass() 59 * { 60 * $this->assertTrue($this->value1 + $this->value2 == 5); 61 * } 62 * ?> 63 * </code> 64 */ 65abstract class PHPUnit_Framework_TestCase extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing 66{ 67 /** 68 * Enable or disable the backup and restoration of the $GLOBALS array. 69 * Overwrite this attribute in a child class of TestCase. 70 * Setting this attribute in setUp() has no effect! 71 * 72 * @var bool 73 */ 74 protected $backupGlobals = null; 75 76 /** 77 * @var array 78 */ 79 protected $backupGlobalsBlacklist = []; 80 81 /** 82 * Enable or disable the backup and restoration of static attributes. 83 * Overwrite this attribute in a child class of TestCase. 84 * Setting this attribute in setUp() has no effect! 85 * 86 * @var bool 87 */ 88 protected $backupStaticAttributes = null; 89 90 /** 91 * @var array 92 */ 93 protected $backupStaticAttributesBlacklist = []; 94 95 /** 96 * Whether or not this test is to be run in a separate PHP process. 97 * 98 * @var bool 99 */ 100 protected $runTestInSeparateProcess = null; 101 102 /** 103 * Whether or not this test should preserve the global state when 104 * running in a separate PHP process. 105 * 106 * @var bool 107 */ 108 protected $preserveGlobalState = true; 109 110 /** 111 * Whether or not this test is running in a separate PHP process. 112 * 113 * @var bool 114 */ 115 private $inIsolation = false; 116 117 /** 118 * @var array 119 */ 120 private $data = []; 121 122 /** 123 * @var string 124 */ 125 private $dataName = ''; 126 127 /** 128 * @var bool 129 */ 130 private $useErrorHandler = null; 131 132 /** 133 * The name of the expected Exception. 134 * 135 * @var string 136 */ 137 private $expectedException = null; 138 139 /** 140 * The message of the expected Exception. 141 * 142 * @var string 143 */ 144 private $expectedExceptionMessage = null; 145 146 /** 147 * The regex pattern to validate the expected Exception message. 148 * 149 * @var string 150 */ 151 private $expectedExceptionMessageRegExp = null; 152 153 /** 154 * The code of the expected Exception. 155 * 156 * @var int|string 157 */ 158 private $expectedExceptionCode = null; 159 160 /** 161 * The name of the test case. 162 * 163 * @var string 164 */ 165 private $name = null; 166 167 /** 168 * @var array 169 */ 170 private $dependencies = []; 171 172 /** 173 * @var array 174 */ 175 private $dependencyInput = []; 176 177 /** 178 * @var array 179 */ 180 private $iniSettings = []; 181 182 /** 183 * @var array 184 */ 185 private $locale = []; 186 187 /** 188 * @var array 189 */ 190 private $mockObjects = []; 191 192 /** 193 * @var MockGenerator 194 */ 195 private $mockObjectGenerator = null; 196 197 /** 198 * @var int 199 */ 200 private $status; 201 202 /** 203 * @var string 204 */ 205 private $statusMessage = ''; 206 207 /** 208 * @var int 209 */ 210 private $numAssertions = 0; 211 212 /** 213 * @var PHPUnit_Framework_TestResult 214 */ 215 private $result; 216 217 /** 218 * @var mixed 219 */ 220 private $testResult; 221 222 /** 223 * @var string 224 */ 225 private $output = ''; 226 227 /** 228 * @var string 229 */ 230 private $outputExpectedRegex = null; 231 232 /** 233 * @var string 234 */ 235 private $outputExpectedString = null; 236 237 /** 238 * @var mixed 239 */ 240 private $outputCallback = false; 241 242 /** 243 * @var bool 244 */ 245 private $outputBufferingActive = false; 246 247 /** 248 * @var int 249 */ 250 private $outputBufferingLevel; 251 252 /** 253 * @var SebastianBergmann\GlobalState\Snapshot 254 */ 255 private $snapshot; 256 257 /** 258 * @var Prophecy\Prophet 259 */ 260 private $prophet; 261 262 /** 263 * @var bool 264 */ 265 private $beStrictAboutChangesToGlobalState = false; 266 267 /** 268 * @var bool 269 */ 270 private $registerMockObjectsFromTestArgumentsRecursively = false; 271 272 /** 273 * @var string[] 274 */ 275 private $warnings = []; 276 277 /** 278 * @var array 279 */ 280 private $groups = []; 281 282 /** 283 * @var bool 284 */ 285 private $doesNotPerformAssertions = false; 286 287 /** 288 * Constructs a test case with the given name. 289 * 290 * @param string $name 291 * @param array $data 292 * @param string $dataName 293 */ 294 public function __construct($name = null, array $data = [], $dataName = '') 295 { 296 if ($name !== null) { 297 $this->setName($name); 298 } 299 300 $this->data = $data; 301 $this->dataName = $dataName; 302 } 303 304 /** 305 * Returns a string representation of the test case. 306 * 307 * @return string 308 */ 309 public function toString() 310 { 311 $class = new ReflectionClass($this); 312 313 $buffer = sprintf( 314 '%s::%s', 315 $class->name, 316 $this->getName(false) 317 ); 318 319 return $buffer . $this->getDataSetAsString(); 320 } 321 322 /** 323 * Counts the number of test cases executed by run(TestResult result). 324 * 325 * @return int 326 */ 327 public function count() 328 { 329 return 1; 330 } 331 332 public function getGroups() 333 { 334 return $this->groups; 335 } 336 337 /** 338 * @param array $groups 339 */ 340 public function setGroups(array $groups) 341 { 342 $this->groups = $groups; 343 } 344 345 /** 346 * Returns the annotations for this test. 347 * 348 * @return array 349 */ 350 public function getAnnotations() 351 { 352 return PHPUnit_Util_Test::parseTestMethodAnnotations( 353 get_class($this), 354 $this->name 355 ); 356 } 357 358 /** 359 * Gets the name of a TestCase. 360 * 361 * @param bool $withDataSet 362 * 363 * @return string 364 */ 365 public function getName($withDataSet = true) 366 { 367 if ($withDataSet) { 368 return $this->name . $this->getDataSetAsString(false); 369 } else { 370 return $this->name; 371 } 372 } 373 374 /** 375 * Returns the size of the test. 376 * 377 * @return int 378 */ 379 public function getSize() 380 { 381 return PHPUnit_Util_Test::getSize( 382 get_class($this), 383 $this->getName(false) 384 ); 385 } 386 387 /** 388 * @return bool 389 */ 390 public function hasSize() 391 { 392 return $this->getSize() !== PHPUnit_Util_Test::UNKNOWN; 393 } 394 395 /** 396 * @return bool 397 */ 398 public function isSmall() 399 { 400 return $this->getSize() === PHPUnit_Util_Test::SMALL; 401 } 402 403 /** 404 * @return bool 405 */ 406 public function isMedium() 407 { 408 return $this->getSize() === PHPUnit_Util_Test::MEDIUM; 409 } 410 411 /** 412 * @return bool 413 */ 414 public function isLarge() 415 { 416 return $this->getSize() === PHPUnit_Util_Test::LARGE; 417 } 418 419 /** 420 * @return string 421 */ 422 public function getActualOutput() 423 { 424 if (!$this->outputBufferingActive) { 425 return $this->output; 426 } else { 427 return ob_get_contents(); 428 } 429 } 430 431 /** 432 * @return bool 433 */ 434 public function hasOutput() 435 { 436 if (strlen($this->output) === 0) { 437 return false; 438 } 439 440 if ($this->hasExpectationOnOutput()) { 441 return false; 442 } 443 444 return true; 445 } 446 447 /** 448 * @return bool 449 */ 450 public function doesNotPerformAssertions() 451 { 452 return $this->doesNotPerformAssertions; 453 } 454 455 /** 456 * @param string $expectedRegex 457 * 458 * @throws PHPUnit_Framework_Exception 459 */ 460 public function expectOutputRegex($expectedRegex) 461 { 462 if ($this->outputExpectedString !== null) { 463 throw new PHPUnit_Framework_Exception; 464 } 465 466 if (is_string($expectedRegex) || is_null($expectedRegex)) { 467 $this->outputExpectedRegex = $expectedRegex; 468 } 469 } 470 471 /** 472 * @param string $expectedString 473 */ 474 public function expectOutputString($expectedString) 475 { 476 if ($this->outputExpectedRegex !== null) { 477 throw new PHPUnit_Framework_Exception; 478 } 479 480 if (is_string($expectedString) || is_null($expectedString)) { 481 $this->outputExpectedString = $expectedString; 482 } 483 } 484 485 /** 486 * @return bool 487 * 488 * @deprecated Use hasExpectationOnOutput() instead 489 */ 490 public function hasPerformedExpectationsOnOutput() 491 { 492 return $this->hasExpectationOnOutput(); 493 } 494 495 /** 496 * @return bool 497 */ 498 public function hasExpectationOnOutput() 499 { 500 return is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex); 501 } 502 503 /** 504 * @return string 505 */ 506 public function getExpectedException() 507 { 508 return $this->expectedException; 509 } 510 511 /** 512 * @param mixed $exception 513 * @param string $message Null means we do not check message at all, string (even empty) means we do. Default: null. 514 * @param int|string $code Null means we do not check code at all, non-null means we do. 515 * 516 * @throws PHPUnit_Framework_Exception 517 * 518 * @deprecated Method deprecated since Release 5.2.0; use expectException() instead 519 */ 520 public function setExpectedException($exception, $message = '', $code = null) 521 { 522 if (null !== $message && !is_string($message)) { 523 throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); 524 } 525 526 if (func_num_args() < 2) { 527 $message = null; 528 } 529 530 $this->expectedException = $exception; 531 532 if ($message !== null) { 533 $this->expectExceptionMessage($message); 534 } 535 536 if ($code !== null) { 537 $this->expectExceptionCode($code); 538 } 539 } 540 541 /** 542 * @param mixed $exception 543 * @param string $messageRegExp 544 * @param int $code 545 * 546 * @throws PHPUnit_Framework_Exception 547 * 548 * @deprecated Method deprecated since Release 5.6.0; use expectExceptionMessageRegExp() instead 549 */ 550 public function setExpectedExceptionRegExp($exception, $messageRegExp = '', $code = null) 551 { 552 if (!is_string($messageRegExp)) { 553 throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); 554 } 555 556 $this->expectedException = $exception; 557 $this->expectedExceptionMessageRegExp = $messageRegExp; 558 559 if ($code !== null) { 560 $this->expectExceptionCode($code); 561 } 562 } 563 564 /** 565 * @param string $exception 566 */ 567 public function expectException($exception) 568 { 569 if (!is_string($exception)) { 570 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); 571 } 572 573 $this->expectedException = $exception; 574 } 575 576 /** 577 * @param int|string $code 578 * 579 * @throws PHPUnit_Framework_Exception 580 */ 581 public function expectExceptionCode($code) 582 { 583 if (!$this->expectedException) { 584 $this->expectedException = \Exception::class; 585 } 586 587 if (!is_int($code) && !is_string($code)) { 588 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer or string'); 589 } 590 591 $this->expectedExceptionCode = $code; 592 } 593 594 /** 595 * @param string $message 596 * 597 * @throws PHPUnit_Framework_Exception 598 */ 599 public function expectExceptionMessage($message) 600 { 601 if (!$this->expectedException) { 602 $this->expectedException = \Exception::class; 603 } 604 605 if (!is_string($message)) { 606 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); 607 } 608 609 $this->expectedExceptionMessage = $message; 610 } 611 612 /** 613 * @param string $messageRegExp 614 * 615 * @throws PHPUnit_Framework_Exception 616 */ 617 public function expectExceptionMessageRegExp($messageRegExp) 618 { 619 if (!is_string($messageRegExp)) { 620 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); 621 } 622 623 $this->expectedExceptionMessageRegExp = $messageRegExp; 624 } 625 626 /** 627 * @param bool $flag 628 */ 629 public function setRegisterMockObjectsFromTestArgumentsRecursively($flag) 630 { 631 if (!is_bool($flag)) { 632 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); 633 } 634 635 $this->registerMockObjectsFromTestArgumentsRecursively = $flag; 636 } 637 638 protected function setExpectedExceptionFromAnnotation() 639 { 640 try { 641 $expectedException = PHPUnit_Util_Test::getExpectedException( 642 get_class($this), 643 $this->name 644 ); 645 646 if ($expectedException !== false) { 647 $this->expectException($expectedException['class']); 648 649 if ($expectedException['code'] !== null) { 650 $this->expectExceptionCode($expectedException['code']); 651 } 652 653 if ($expectedException['message'] !== '') { 654 $this->expectExceptionMessage($expectedException['message']); 655 } elseif ($expectedException['message_regex'] !== '') { 656 $this->expectExceptionMessageRegExp($expectedException['message_regex']); 657 } 658 } 659 } catch (ReflectionException $e) { 660 } 661 } 662 663 /** 664 * @param bool $useErrorHandler 665 */ 666 public function setUseErrorHandler($useErrorHandler) 667 { 668 $this->useErrorHandler = $useErrorHandler; 669 } 670 671 protected function setUseErrorHandlerFromAnnotation() 672 { 673 try { 674 $useErrorHandler = PHPUnit_Util_Test::getErrorHandlerSettings( 675 get_class($this), 676 $this->name 677 ); 678 679 if ($useErrorHandler !== null) { 680 $this->setUseErrorHandler($useErrorHandler); 681 } 682 } catch (ReflectionException $e) { 683 } 684 } 685 686 protected function checkRequirements() 687 { 688 if (!$this->name || !method_exists($this, $this->name)) { 689 return; 690 } 691 692 $missingRequirements = PHPUnit_Util_Test::getMissingRequirements( 693 get_class($this), 694 $this->name 695 ); 696 697 if (!empty($missingRequirements)) { 698 $this->markTestSkipped(implode(PHP_EOL, $missingRequirements)); 699 } 700 } 701 702 /** 703 * Returns the status of this test. 704 * 705 * @return int 706 */ 707 public function getStatus() 708 { 709 return $this->status; 710 } 711 712 public function markAsRisky() 713 { 714 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_RISKY; 715 } 716 717 /** 718 * Returns the status message of this test. 719 * 720 * @return string 721 */ 722 public function getStatusMessage() 723 { 724 return $this->statusMessage; 725 } 726 727 /** 728 * Returns whether or not this test has failed. 729 * 730 * @return bool 731 */ 732 public function hasFailed() 733 { 734 $status = $this->getStatus(); 735 736 return $status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE || 737 $status == PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; 738 } 739 740 /** 741 * Runs the test case and collects the results in a TestResult object. 742 * If no TestResult object is passed a new one will be created. 743 * 744 * @param PHPUnit_Framework_TestResult $result 745 * 746 * @return PHPUnit_Framework_TestResult 747 * 748 * @throws PHPUnit_Framework_Exception 749 */ 750 public function run(PHPUnit_Framework_TestResult $result = null) 751 { 752 if ($result === null) { 753 $result = $this->createResult(); 754 } 755 756 if (!$this instanceof PHPUnit_Framework_WarningTestCase) { 757 $this->setTestResultObject($result); 758 $this->setUseErrorHandlerFromAnnotation(); 759 } 760 761 if ($this->useErrorHandler !== null) { 762 $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions(); 763 $result->convertErrorsToExceptions($this->useErrorHandler); 764 } 765 766 if (!$this instanceof PHPUnit_Framework_WarningTestCase && 767 !$this instanceof PHPUnit_Framework_SkippedTestCase && 768 !$this->handleDependencies()) { 769 return; 770 } 771 772 if ($this->runTestInSeparateProcess === true && 773 $this->inIsolation !== true && 774 !$this instanceof PHPUnit_Extensions_PhptTestCase) { 775 $class = new ReflectionClass($this); 776 777 $template = new Text_Template( 778 __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl' 779 ); 780 781 if ($this->preserveGlobalState) { 782 $constants = PHPUnit_Util_GlobalState::getConstantsAsString(); 783 $globals = PHPUnit_Util_GlobalState::getGlobalsAsString(); 784 $includedFiles = PHPUnit_Util_GlobalState::getIncludedFilesAsString(); 785 $iniSettings = PHPUnit_Util_GlobalState::getIniSettingsAsString(); 786 } else { 787 $constants = ''; 788 if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { 789 $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n"; 790 } else { 791 $globals = ''; 792 } 793 $includedFiles = ''; 794 $iniSettings = ''; 795 } 796 797 $coverage = $result->getCollectCodeCoverageInformation() ? 'true' : 'false'; 798 $isStrictAboutTestsThatDoNotTestAnything = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false'; 799 $isStrictAboutOutputDuringTests = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false'; 800 $enforcesTimeLimit = $result->enforcesTimeLimit() ? 'true' : 'false'; 801 $isStrictAboutTodoAnnotatedTests = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false'; 802 $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false'; 803 804 if (defined('PHPUNIT_COMPOSER_INSTALL')) { 805 $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); 806 } else { 807 $composerAutoload = '\'\''; 808 } 809 810 if (defined('__PHPUNIT_PHAR__')) { 811 $phar = var_export(__PHPUNIT_PHAR__, true); 812 } else { 813 $phar = '\'\''; 814 } 815 816 if ($result->getCodeCoverage()) { 817 $codeCoverageFilter = $result->getCodeCoverage()->filter(); 818 } else { 819 $codeCoverageFilter = null; 820 } 821 822 $data = var_export(serialize($this->data), true); 823 $dataName = var_export($this->dataName, true); 824 $dependencyInput = var_export(serialize($this->dependencyInput), true); 825 $includePath = var_export(get_include_path(), true); 826 $codeCoverageFilter = var_export(serialize($codeCoverageFilter), true); 827 // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC 828 // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences 829 $data = "'." . $data . ".'"; 830 $dataName = "'.(" . $dataName . ").'"; 831 $dependencyInput = "'." . $dependencyInput . ".'"; 832 $includePath = "'." . $includePath . ".'"; 833 $codeCoverageFilter = "'." . $codeCoverageFilter . ".'"; 834 835 $configurationFilePath = (isset($GLOBALS['__PHPUNIT_CONFIGURATION_FILE']) ? $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] : ''); 836 837 $template->setVar( 838 [ 839 'composerAutoload' => $composerAutoload, 840 'phar' => $phar, 841 'filename' => $class->getFileName(), 842 'className' => $class->getName(), 843 'methodName' => $this->name, 844 'collectCodeCoverageInformation' => $coverage, 845 'data' => $data, 846 'dataName' => $dataName, 847 'dependencyInput' => $dependencyInput, 848 'constants' => $constants, 849 'globals' => $globals, 850 'include_path' => $includePath, 851 'included_files' => $includedFiles, 852 'iniSettings' => $iniSettings, 853 'isStrictAboutTestsThatDoNotTestAnything' => $isStrictAboutTestsThatDoNotTestAnything, 854 'isStrictAboutOutputDuringTests' => $isStrictAboutOutputDuringTests, 855 'enforcesTimeLimit' => $enforcesTimeLimit, 856 'isStrictAboutTodoAnnotatedTests' => $isStrictAboutTodoAnnotatedTests, 857 'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests, 858 'codeCoverageFilter' => $codeCoverageFilter, 859 'configurationFilePath' => $configurationFilePath 860 ] 861 ); 862 863 $this->prepareTemplate($template); 864 865 $php = PHPUnit_Util_PHP::factory(); 866 $php->runTestJob($template->render(), $this, $result); 867 } else { 868 $result->run($this); 869 } 870 871 if (isset($oldErrorHandlerSetting)) { 872 $result->convertErrorsToExceptions($oldErrorHandlerSetting); 873 } 874 875 $this->result = null; 876 877 return $result; 878 } 879 880 /** 881 * Runs the bare test sequence. 882 */ 883 public function runBare() 884 { 885 $this->numAssertions = 0; 886 887 $this->snapshotGlobalState(); 888 $this->startOutputBuffering(); 889 clearstatcache(); 890 $currentWorkingDirectory = getcwd(); 891 892 $hookMethods = PHPUnit_Util_Test::getHookMethods(get_class($this)); 893 894 try { 895 $hasMetRequirements = false; 896 $this->checkRequirements(); 897 $hasMetRequirements = true; 898 899 if ($this->inIsolation) { 900 foreach ($hookMethods['beforeClass'] as $method) { 901 $this->$method(); 902 } 903 } 904 905 $this->setExpectedExceptionFromAnnotation(); 906 $this->setDoesNotPerformAssertionsFromAnnotation(); 907 908 foreach ($hookMethods['before'] as $method) { 909 $this->$method(); 910 } 911 912 $this->assertPreConditions(); 913 $this->testResult = $this->runTest(); 914 $this->verifyMockObjects(); 915 $this->assertPostConditions(); 916 917 if (!empty($this->warnings)) { 918 throw new PHPUnit_Framework_Warning( 919 implode( 920 "\n", 921 array_unique($this->warnings) 922 ) 923 ); 924 } 925 926 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED; 927 } catch (PHPUnit_Framework_IncompleteTest $e) { 928 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE; 929 $this->statusMessage = $e->getMessage(); 930 } catch (PHPUnit_Framework_SkippedTest $e) { 931 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED; 932 $this->statusMessage = $e->getMessage(); 933 } catch (PHPUnit_Framework_Warning $e) { 934 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_WARNING; 935 $this->statusMessage = $e->getMessage(); 936 } catch (PHPUnit_Framework_AssertionFailedError $e) { 937 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; 938 $this->statusMessage = $e->getMessage(); 939 } catch (PredictionException $e) { 940 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; 941 $this->statusMessage = $e->getMessage(); 942 } catch (Throwable $_e) { 943 $e = $_e; 944 } catch (Exception $_e) { 945 $e = $_e; 946 } 947 948 // Clean up the mock objects. 949 $this->mockObjects = []; 950 $this->prophet = null; 951 952 // Tear down the fixture. An exception raised in tearDown() will be 953 // caught and passed on when no exception was raised before. 954 try { 955 if ($hasMetRequirements) { 956 foreach ($hookMethods['after'] as $method) { 957 $this->$method(); 958 } 959 960 if ($this->inIsolation) { 961 foreach ($hookMethods['afterClass'] as $method) { 962 $this->$method(); 963 } 964 } 965 } 966 } catch (Throwable $_e) { 967 if (!isset($e)) { 968 $e = $_e; 969 } 970 } catch (Exception $_e) { 971 if (!isset($e)) { 972 $e = $_e; 973 } 974 } 975 976 try { 977 $this->stopOutputBuffering(); 978 } catch (PHPUnit_Framework_RiskyTestError $_e) { 979 if (!isset($e)) { 980 $e = $_e; 981 } 982 } 983 984 if (isset($_e)) { 985 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; 986 $this->statusMessage = $_e->getMessage(); 987 } 988 989 clearstatcache(); 990 991 if ($currentWorkingDirectory != getcwd()) { 992 chdir($currentWorkingDirectory); 993 } 994 995 $this->restoreGlobalState(); 996 997 // Clean up INI settings. 998 foreach ($this->iniSettings as $varName => $oldValue) { 999 ini_set($varName, $oldValue); 1000 } 1001 1002 $this->iniSettings = []; 1003 1004 // Clean up locale settings. 1005 foreach ($this->locale as $category => $locale) { 1006 setlocale($category, $locale); 1007 } 1008 1009 // Perform assertion on output. 1010 if (!isset($e)) { 1011 try { 1012 if ($this->outputExpectedRegex !== null) { 1013 $this->assertRegExp($this->outputExpectedRegex, $this->output); 1014 } elseif ($this->outputExpectedString !== null) { 1015 $this->assertEquals($this->outputExpectedString, $this->output); 1016 } 1017 } catch (Throwable $_e) { 1018 $e = $_e; 1019 } catch (Exception $_e) { 1020 $e = $_e; 1021 } 1022 } 1023 1024 // Workaround for missing "finally". 1025 if (isset($e)) { 1026 if ($e instanceof PredictionException) { 1027 $e = new PHPUnit_Framework_AssertionFailedError($e->getMessage()); 1028 } 1029 1030 $this->onNotSuccessfulTest($e); 1031 } 1032 } 1033 1034 /** 1035 * Override to run the test and assert its state. 1036 * 1037 * @return mixed 1038 * 1039 * @throws Exception|PHPUnit_Framework_Exception 1040 * @throws PHPUnit_Framework_Exception 1041 */ 1042 protected function runTest() 1043 { 1044 if ($this->name === null) { 1045 throw new PHPUnit_Framework_Exception( 1046 'PHPUnit_Framework_TestCase::$name must not be null.' 1047 ); 1048 } 1049 1050 try { 1051 $class = new ReflectionClass($this); 1052 $method = $class->getMethod($this->name); 1053 } catch (ReflectionException $e) { 1054 $this->fail($e->getMessage()); 1055 } 1056 1057 $testArguments = array_merge($this->data, $this->dependencyInput); 1058 1059 $this->registerMockObjectsFromTestArguments($testArguments); 1060 1061 try { 1062 $testResult = $method->invokeArgs($this, $testArguments); 1063 } catch (Throwable $_e) { 1064 $e = $_e; 1065 } catch (Exception $_e) { 1066 $e = $_e; 1067 } 1068 1069 if (isset($e)) { 1070 $checkException = false; 1071 1072 if (!($e instanceof PHPUnit_Framework_SkippedTestError) && is_string($this->expectedException)) { 1073 $checkException = true; 1074 1075 if ($e instanceof PHPUnit_Framework_Exception) { 1076 $checkException = false; 1077 } 1078 1079 $reflector = new ReflectionClass($this->expectedException); 1080 1081 if ($this->expectedException === 'PHPUnit_Framework_Exception' || 1082 $this->expectedException === '\PHPUnit_Framework_Exception' || 1083 $reflector->isSubclassOf('PHPUnit_Framework_Exception')) { 1084 $checkException = true; 1085 } 1086 } 1087 1088 if ($checkException) { 1089 $this->assertThat( 1090 $e, 1091 new PHPUnit_Framework_Constraint_Exception( 1092 $this->expectedException 1093 ) 1094 ); 1095 1096 if ($this->expectedExceptionMessage !== null) { 1097 $this->assertThat( 1098 $e, 1099 new PHPUnit_Framework_Constraint_ExceptionMessage( 1100 $this->expectedExceptionMessage 1101 ) 1102 ); 1103 } 1104 1105 if ($this->expectedExceptionMessageRegExp !== null) { 1106 $this->assertThat( 1107 $e, 1108 new PHPUnit_Framework_Constraint_ExceptionMessageRegExp( 1109 $this->expectedExceptionMessageRegExp 1110 ) 1111 ); 1112 } 1113 1114 if ($this->expectedExceptionCode !== null) { 1115 $this->assertThat( 1116 $e, 1117 new PHPUnit_Framework_Constraint_ExceptionCode( 1118 $this->expectedExceptionCode 1119 ) 1120 ); 1121 } 1122 1123 return; 1124 } else { 1125 throw $e; 1126 } 1127 } 1128 1129 if ($this->expectedException !== null) { 1130 $this->assertThat( 1131 null, 1132 new PHPUnit_Framework_Constraint_Exception( 1133 $this->expectedException 1134 ) 1135 ); 1136 } 1137 1138 return $testResult; 1139 } 1140 1141 /** 1142 * Verifies the mock object expectations. 1143 */ 1144 protected function verifyMockObjects() 1145 { 1146 foreach ($this->mockObjects as $mockObject) { 1147 if ($mockObject->__phpunit_hasMatchers()) { 1148 $this->numAssertions++; 1149 } 1150 1151 $mockObject->__phpunit_verify( 1152 $this->shouldInvocationMockerBeReset($mockObject) 1153 ); 1154 } 1155 1156 if ($this->prophet !== null) { 1157 try { 1158 $this->prophet->checkPredictions(); 1159 } catch (Throwable $t) { 1160 /* Intentionally left empty */ 1161 } catch (Exception $t) { 1162 /* Intentionally left empty */ 1163 } 1164 1165 foreach ($this->prophet->getProphecies() as $objectProphecy) { 1166 foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { 1167 foreach ($methodProphecies as $methodProphecy) { 1168 $this->numAssertions += count($methodProphecy->getCheckedPredictions()); 1169 } 1170 } 1171 } 1172 1173 if (isset($t)) { 1174 throw $t; 1175 } 1176 } 1177 } 1178 1179 /** 1180 * Sets the name of a TestCase. 1181 * 1182 * @param string 1183 */ 1184 public function setName($name) 1185 { 1186 $this->name = $name; 1187 } 1188 1189 /** 1190 * Sets the dependencies of a TestCase. 1191 * 1192 * @param array $dependencies 1193 */ 1194 public function setDependencies(array $dependencies) 1195 { 1196 $this->dependencies = $dependencies; 1197 } 1198 1199 /** 1200 * Returns true if the tests has dependencies 1201 * 1202 * @return bool 1203 */ 1204 public function hasDependencies() 1205 { 1206 return count($this->dependencies) > 0; 1207 } 1208 1209 /** 1210 * Sets 1211 * 1212 * @param array $dependencyInput 1213 */ 1214 public function setDependencyInput(array $dependencyInput) 1215 { 1216 $this->dependencyInput = $dependencyInput; 1217 } 1218 1219 /** 1220 * @param bool $beStrictAboutChangesToGlobalState 1221 */ 1222 public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState) 1223 { 1224 $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; 1225 } 1226 1227 /** 1228 * Calling this method in setUp() has no effect! 1229 * 1230 * @param bool $backupGlobals 1231 */ 1232 public function setBackupGlobals($backupGlobals) 1233 { 1234 if (is_null($this->backupGlobals) && is_bool($backupGlobals)) { 1235 $this->backupGlobals = $backupGlobals; 1236 } 1237 } 1238 1239 /** 1240 * Calling this method in setUp() has no effect! 1241 * 1242 * @param bool $backupStaticAttributes 1243 */ 1244 public function setBackupStaticAttributes($backupStaticAttributes) 1245 { 1246 if (is_null($this->backupStaticAttributes) && 1247 is_bool($backupStaticAttributes)) { 1248 $this->backupStaticAttributes = $backupStaticAttributes; 1249 } 1250 } 1251 1252 /** 1253 * @param bool $runTestInSeparateProcess 1254 * 1255 * @throws PHPUnit_Framework_Exception 1256 */ 1257 public function setRunTestInSeparateProcess($runTestInSeparateProcess) 1258 { 1259 if (is_bool($runTestInSeparateProcess)) { 1260 if ($this->runTestInSeparateProcess === null) { 1261 $this->runTestInSeparateProcess = $runTestInSeparateProcess; 1262 } 1263 } else { 1264 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); 1265 } 1266 } 1267 1268 /** 1269 * @param bool $preserveGlobalState 1270 * 1271 * @throws PHPUnit_Framework_Exception 1272 */ 1273 public function setPreserveGlobalState($preserveGlobalState) 1274 { 1275 if (is_bool($preserveGlobalState)) { 1276 $this->preserveGlobalState = $preserveGlobalState; 1277 } else { 1278 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); 1279 } 1280 } 1281 1282 /** 1283 * @param bool $inIsolation 1284 * 1285 * @throws PHPUnit_Framework_Exception 1286 */ 1287 public function setInIsolation($inIsolation) 1288 { 1289 if (is_bool($inIsolation)) { 1290 $this->inIsolation = $inIsolation; 1291 } else { 1292 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); 1293 } 1294 } 1295 1296 /** 1297 * @return bool 1298 */ 1299 public function isInIsolation() 1300 { 1301 return $this->inIsolation; 1302 } 1303 1304 /** 1305 * @return mixed 1306 */ 1307 public function getResult() 1308 { 1309 return $this->testResult; 1310 } 1311 1312 /** 1313 * @param mixed $result 1314 */ 1315 public function setResult($result) 1316 { 1317 $this->testResult = $result; 1318 } 1319 1320 /** 1321 * @param callable $callback 1322 * 1323 * @throws PHPUnit_Framework_Exception 1324 */ 1325 public function setOutputCallback($callback) 1326 { 1327 if (!is_callable($callback)) { 1328 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'callback'); 1329 } 1330 1331 $this->outputCallback = $callback; 1332 } 1333 1334 /** 1335 * @return PHPUnit_Framework_TestResult 1336 */ 1337 public function getTestResultObject() 1338 { 1339 return $this->result; 1340 } 1341 1342 /** 1343 * @param PHPUnit_Framework_TestResult $result 1344 */ 1345 public function setTestResultObject(PHPUnit_Framework_TestResult $result) 1346 { 1347 $this->result = $result; 1348 } 1349 1350 /** 1351 * @param PHPUnit_Framework_MockObject_MockObject $mockObject 1352 */ 1353 public function registerMockObject(PHPUnit_Framework_MockObject_MockObject $mockObject) 1354 { 1355 $this->mockObjects[] = $mockObject; 1356 } 1357 1358 /** 1359 * This method is a wrapper for the ini_set() function that automatically 1360 * resets the modified php.ini setting to its original value after the 1361 * test is run. 1362 * 1363 * @param string $varName 1364 * @param string $newValue 1365 * 1366 * @throws PHPUnit_Framework_Exception 1367 */ 1368 protected function iniSet($varName, $newValue) 1369 { 1370 if (!is_string($varName)) { 1371 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); 1372 } 1373 1374 $currentValue = ini_set($varName, $newValue); 1375 1376 if ($currentValue !== false) { 1377 $this->iniSettings[$varName] = $currentValue; 1378 } else { 1379 throw new PHPUnit_Framework_Exception( 1380 sprintf( 1381 'INI setting "%s" could not be set to "%s".', 1382 $varName, 1383 $newValue 1384 ) 1385 ); 1386 } 1387 } 1388 1389 /** 1390 * This method is a wrapper for the setlocale() function that automatically 1391 * resets the locale to its original value after the test is run. 1392 * 1393 * @param int $category 1394 * @param string $locale 1395 * 1396 * @throws PHPUnit_Framework_Exception 1397 */ 1398 protected function setLocale() 1399 { 1400 $args = func_get_args(); 1401 1402 if (count($args) < 2) { 1403 throw new PHPUnit_Framework_Exception; 1404 } 1405 1406 $category = $args[0]; 1407 $locale = $args[1]; 1408 1409 $categories = [ 1410 LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME 1411 ]; 1412 1413 if (defined('LC_MESSAGES')) { 1414 $categories[] = LC_MESSAGES; 1415 } 1416 1417 if (!in_array($category, $categories)) { 1418 throw new PHPUnit_Framework_Exception; 1419 } 1420 1421 if (!is_array($locale) && !is_string($locale)) { 1422 throw new PHPUnit_Framework_Exception; 1423 } 1424 1425 $this->locale[$category] = setlocale($category, 0); 1426 1427 $result = call_user_func_array('setlocale', $args); 1428 1429 if ($result === false) { 1430 throw new PHPUnit_Framework_Exception( 1431 'The locale functionality is not implemented on your platform, ' . 1432 'the specified locale does not exist or the category name is ' . 1433 'invalid.' 1434 ); 1435 } 1436 } 1437 1438 /** 1439 * Returns a builder object to create mock objects using a fluent interface. 1440 * 1441 * @param string|string[] $className 1442 * 1443 * @return PHPUnit_Framework_MockObject_MockBuilder 1444 */ 1445 public function getMockBuilder($className) 1446 { 1447 return new PHPUnit_Framework_MockObject_MockBuilder($this, $className); 1448 } 1449 1450 /** 1451 * Returns a test double for the specified class. 1452 * 1453 * @param string $originalClassName 1454 * 1455 * @return PHPUnit_Framework_MockObject_MockObject 1456 * 1457 * @throws PHPUnit_Framework_Exception 1458 */ 1459 protected function createMock($originalClassName) 1460 { 1461 return $this->getMockBuilder($originalClassName) 1462 ->disableOriginalConstructor() 1463 ->disableOriginalClone() 1464 ->disableArgumentCloning() 1465 ->disallowMockingUnknownTypes() 1466 ->getMock(); 1467 } 1468 1469 /** 1470 * Returns a configured test double for the specified class. 1471 * 1472 * @param string $originalClassName 1473 * @param array $configuration 1474 * 1475 * @return PHPUnit_Framework_MockObject_MockObject 1476 * 1477 * @throws PHPUnit_Framework_Exception 1478 */ 1479 protected function createConfiguredMock($originalClassName, array $configuration) 1480 { 1481 $o = $this->createMock($originalClassName); 1482 1483 foreach ($configuration as $method => $return) { 1484 $o->method($method)->willReturn($return); 1485 } 1486 1487 return $o; 1488 } 1489 1490 /** 1491 * Returns a partial test double for the specified class. 1492 * 1493 * @param string $originalClassName 1494 * @param array $methods 1495 * 1496 * @return PHPUnit_Framework_MockObject_MockObject 1497 * 1498 * @throws PHPUnit_Framework_Exception 1499 */ 1500 protected function createPartialMock($originalClassName, array $methods) 1501 { 1502 return $this->getMockBuilder($originalClassName) 1503 ->disableOriginalConstructor() 1504 ->disableOriginalClone() 1505 ->disableArgumentCloning() 1506 ->disallowMockingUnknownTypes() 1507 ->setMethods(empty($methods) ? null : $methods) 1508 ->getMock(); 1509 } 1510 1511 /** 1512 * Returns a mock object for the specified class. 1513 * 1514 * @param string $originalClassName Name of the class to mock. 1515 * @param array|null $methods When provided, only methods whose names are in the array 1516 * are replaced with a configurable test double. The behavior 1517 * of the other methods is not changed. 1518 * Providing null means that no methods will be replaced. 1519 * @param array $arguments Parameters to pass to the original class' constructor. 1520 * @param string $mockClassName Class name for the generated test double class. 1521 * @param bool $callOriginalConstructor Can be used to disable the call to the original class' constructor. 1522 * @param bool $callOriginalClone Can be used to disable the call to the original class' clone constructor. 1523 * @param bool $callAutoload Can be used to disable __autoload() during the generation of the test double class. 1524 * @param bool $cloneArguments 1525 * @param bool $callOriginalMethods 1526 * @param object $proxyTarget 1527 * 1528 * @return PHPUnit_Framework_MockObject_MockObject 1529 * 1530 * @throws PHPUnit_Framework_Exception 1531 * 1532 * @deprecated Method deprecated since Release 5.4.0; use createMock() or getMockBuilder() instead 1533 */ 1534 protected function getMock($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) 1535 { 1536 $this->warnings[] = 'PHPUnit_Framework_TestCase::getMock() is deprecated, use PHPUnit_Framework_TestCase::createMock() or PHPUnit_Framework_TestCase::getMockBuilder() instead'; 1537 1538 $mockObject = $this->getMockObjectGenerator()->getMock( 1539 $originalClassName, 1540 $methods, 1541 $arguments, 1542 $mockClassName, 1543 $callOriginalConstructor, 1544 $callOriginalClone, 1545 $callAutoload, 1546 $cloneArguments, 1547 $callOriginalMethods, 1548 $proxyTarget 1549 ); 1550 1551 $this->registerMockObject($mockObject); 1552 1553 return $mockObject; 1554 } 1555 1556 /** 1557 * Returns a mock with disabled constructor object for the specified class. 1558 * 1559 * @param string $originalClassName 1560 * 1561 * @return PHPUnit_Framework_MockObject_MockObject 1562 * 1563 * @throws PHPUnit_Framework_Exception 1564 * 1565 * @deprecated Method deprecated since Release 5.4.0; use createMock() instead 1566 */ 1567 protected function getMockWithoutInvokingTheOriginalConstructor($originalClassName) 1568 { 1569 $this->warnings[] = 'PHPUnit_Framework_TestCase::getMockWithoutInvokingTheOriginalConstructor() is deprecated, use PHPUnit_Framework_TestCase::createMock() instead'; 1570 1571 return $this->getMockBuilder($originalClassName) 1572 ->disableOriginalConstructor() 1573 ->getMock(); 1574 } 1575 1576 /** 1577 * Mocks the specified class and returns the name of the mocked class. 1578 * 1579 * @param string $originalClassName 1580 * @param array $methods 1581 * @param array $arguments 1582 * @param string $mockClassName 1583 * @param bool $callOriginalConstructor 1584 * @param bool $callOriginalClone 1585 * @param bool $callAutoload 1586 * @param bool $cloneArguments 1587 * 1588 * @return string 1589 * 1590 * @throws PHPUnit_Framework_Exception 1591 */ 1592 protected function getMockClass($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false) 1593 { 1594 $mock = $this->getMockObjectGenerator()->getMock( 1595 $originalClassName, 1596 $methods, 1597 $arguments, 1598 $mockClassName, 1599 $callOriginalConstructor, 1600 $callOriginalClone, 1601 $callAutoload, 1602 $cloneArguments 1603 ); 1604 1605 return get_class($mock); 1606 } 1607 1608 /** 1609 * Returns a mock object for the specified abstract class with all abstract 1610 * methods of the class mocked. Concrete methods are not mocked by default. 1611 * To mock concrete methods, use the 7th parameter ($mockedMethods). 1612 * 1613 * @param string $originalClassName 1614 * @param array $arguments 1615 * @param string $mockClassName 1616 * @param bool $callOriginalConstructor 1617 * @param bool $callOriginalClone 1618 * @param bool $callAutoload 1619 * @param array $mockedMethods 1620 * @param bool $cloneArguments 1621 * 1622 * @return PHPUnit_Framework_MockObject_MockObject 1623 * 1624 * @throws PHPUnit_Framework_Exception 1625 */ 1626 protected function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false) 1627 { 1628 $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass( 1629 $originalClassName, 1630 $arguments, 1631 $mockClassName, 1632 $callOriginalConstructor, 1633 $callOriginalClone, 1634 $callAutoload, 1635 $mockedMethods, 1636 $cloneArguments 1637 ); 1638 1639 $this->registerMockObject($mockObject); 1640 1641 return $mockObject; 1642 } 1643 1644 /** 1645 * Returns a mock object based on the given WSDL file. 1646 * 1647 * @param string $wsdlFile 1648 * @param string $originalClassName 1649 * @param string $mockClassName 1650 * @param array $methods 1651 * @param bool $callOriginalConstructor 1652 * @param array $options An array of options passed to SOAPClient::_construct 1653 * 1654 * @return PHPUnit_Framework_MockObject_MockObject 1655 */ 1656 protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = [], $callOriginalConstructor = true, array $options = []) 1657 { 1658 if ($originalClassName === '') { 1659 $originalClassName = pathinfo(basename(parse_url($wsdlFile)['path']), PATHINFO_FILENAME); 1660 } 1661 1662 if (!class_exists($originalClassName)) { 1663 eval( 1664 $this->getMockObjectGenerator()->generateClassFromWsdl( 1665 $wsdlFile, 1666 $originalClassName, 1667 $methods, 1668 $options 1669 ) 1670 ); 1671 } 1672 1673 $mockObject = $this->getMockObjectGenerator()->getMock( 1674 $originalClassName, 1675 $methods, 1676 ['', $options], 1677 $mockClassName, 1678 $callOriginalConstructor, 1679 false, 1680 false 1681 ); 1682 1683 $this->registerMockObject($mockObject); 1684 1685 return $mockObject; 1686 } 1687 1688 /** 1689 * Returns a mock object for the specified trait with all abstract methods 1690 * of the trait mocked. Concrete methods to mock can be specified with the 1691 * `$mockedMethods` parameter. 1692 * 1693 * @param string $traitName 1694 * @param array $arguments 1695 * @param string $mockClassName 1696 * @param bool $callOriginalConstructor 1697 * @param bool $callOriginalClone 1698 * @param bool $callAutoload 1699 * @param array $mockedMethods 1700 * @param bool $cloneArguments 1701 * 1702 * @return PHPUnit_Framework_MockObject_MockObject 1703 * 1704 * @throws PHPUnit_Framework_Exception 1705 */ 1706 protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false) 1707 { 1708 $mockObject = $this->getMockObjectGenerator()->getMockForTrait( 1709 $traitName, 1710 $arguments, 1711 $mockClassName, 1712 $callOriginalConstructor, 1713 $callOriginalClone, 1714 $callAutoload, 1715 $mockedMethods, 1716 $cloneArguments 1717 ); 1718 1719 $this->registerMockObject($mockObject); 1720 1721 return $mockObject; 1722 } 1723 1724 /** 1725 * Returns an object for the specified trait. 1726 * 1727 * @param string $traitName 1728 * @param array $arguments 1729 * @param string $traitClassName 1730 * @param bool $callOriginalConstructor 1731 * @param bool $callOriginalClone 1732 * @param bool $callAutoload 1733 * @param bool $cloneArguments 1734 * 1735 * @return object 1736 * 1737 * @throws PHPUnit_Framework_Exception 1738 */ 1739 protected function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false) 1740 { 1741 return $this->getMockObjectGenerator()->getObjectForTrait( 1742 $traitName, 1743 $arguments, 1744 $traitClassName, 1745 $callOriginalConstructor, 1746 $callOriginalClone, 1747 $callAutoload, 1748 $cloneArguments 1749 ); 1750 } 1751 1752 /** 1753 * @param string|null $classOrInterface 1754 * 1755 * @return \Prophecy\Prophecy\ObjectProphecy 1756 * 1757 * @throws \LogicException 1758 */ 1759 protected function prophesize($classOrInterface = null) 1760 { 1761 return $this->getProphet()->prophesize($classOrInterface); 1762 } 1763 1764 /** 1765 * Adds a value to the assertion counter. 1766 * 1767 * @param int $count 1768 */ 1769 public function addToAssertionCount($count) 1770 { 1771 $this->numAssertions += $count; 1772 } 1773 1774 /** 1775 * Returns the number of assertions performed by this test. 1776 * 1777 * @return int 1778 */ 1779 public function getNumAssertions() 1780 { 1781 return $this->numAssertions; 1782 } 1783 1784 /** 1785 * Returns a matcher that matches when the method is executed 1786 * zero or more times. 1787 * 1788 * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount 1789 */ 1790 public static function any() 1791 { 1792 return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount; 1793 } 1794 1795 /** 1796 * Returns a matcher that matches when the method is never executed. 1797 * 1798 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount 1799 */ 1800 public static function never() 1801 { 1802 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0); 1803 } 1804 1805 /** 1806 * Returns a matcher that matches when the method is executed 1807 * at least N times. 1808 * 1809 * @param int $requiredInvocations 1810 * 1811 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount 1812 */ 1813 public static function atLeast($requiredInvocations) 1814 { 1815 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount( 1816 $requiredInvocations 1817 ); 1818 } 1819 1820 /** 1821 * Returns a matcher that matches when the method is executed at least once. 1822 * 1823 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce 1824 */ 1825 public static function atLeastOnce() 1826 { 1827 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce; 1828 } 1829 1830 /** 1831 * Returns a matcher that matches when the method is executed exactly once. 1832 * 1833 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount 1834 */ 1835 public static function once() 1836 { 1837 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1); 1838 } 1839 1840 /** 1841 * Returns a matcher that matches when the method is executed 1842 * exactly $count times. 1843 * 1844 * @param int $count 1845 * 1846 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount 1847 */ 1848 public static function exactly($count) 1849 { 1850 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count); 1851 } 1852 1853 /** 1854 * Returns a matcher that matches when the method is executed 1855 * at most N times. 1856 * 1857 * @param int $allowedInvocations 1858 * 1859 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount 1860 */ 1861 public static function atMost($allowedInvocations) 1862 { 1863 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount( 1864 $allowedInvocations 1865 ); 1866 } 1867 1868 /** 1869 * Returns a matcher that matches when the method is executed 1870 * at the given index. 1871 * 1872 * @param int $index 1873 * 1874 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex 1875 */ 1876 public static function at($index) 1877 { 1878 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index); 1879 } 1880 1881 /** 1882 * @param mixed $value 1883 * 1884 * @return PHPUnit_Framework_MockObject_Stub_Return 1885 */ 1886 public static function returnValue($value) 1887 { 1888 return new PHPUnit_Framework_MockObject_Stub_Return($value); 1889 } 1890 1891 /** 1892 * @param array $valueMap 1893 * 1894 * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap 1895 */ 1896 public static function returnValueMap(array $valueMap) 1897 { 1898 return new PHPUnit_Framework_MockObject_Stub_ReturnValueMap($valueMap); 1899 } 1900 1901 /** 1902 * @param int $argumentIndex 1903 * 1904 * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument 1905 */ 1906 public static function returnArgument($argumentIndex) 1907 { 1908 return new PHPUnit_Framework_MockObject_Stub_ReturnArgument( 1909 $argumentIndex 1910 ); 1911 } 1912 1913 /** 1914 * @param mixed $callback 1915 * 1916 * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback 1917 */ 1918 public static function returnCallback($callback) 1919 { 1920 return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback); 1921 } 1922 1923 /** 1924 * Returns the current object. 1925 * 1926 * This method is useful when mocking a fluent interface. 1927 * 1928 * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf 1929 */ 1930 public static function returnSelf() 1931 { 1932 return new PHPUnit_Framework_MockObject_Stub_ReturnSelf(); 1933 } 1934 1935 /** 1936 * @param Throwable|Exception $exception 1937 * 1938 * @return PHPUnit_Framework_MockObject_Stub_Exception 1939 * 1940 * @todo Add type declaration when support for PHP 5 is dropped 1941 */ 1942 public static function throwException($exception) 1943 { 1944 return new PHPUnit_Framework_MockObject_Stub_Exception($exception); 1945 } 1946 1947 /** 1948 * @param mixed $value, ... 1949 * 1950 * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls 1951 */ 1952 public static function onConsecutiveCalls() 1953 { 1954 $args = func_get_args(); 1955 1956 return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args); 1957 } 1958 1959 /** 1960 * @return bool 1961 */ 1962 public function usesDataProvider() 1963 { 1964 return !empty($this->data); 1965 } 1966 1967 /** 1968 * @return string 1969 */ 1970 public function dataDescription() 1971 { 1972 return is_string($this->dataName) ? $this->dataName : ''; 1973 } 1974 1975 /** 1976 * Gets the data set description of a TestCase. 1977 * 1978 * @param bool $includeData 1979 * 1980 * @return string 1981 */ 1982 protected function getDataSetAsString($includeData = true) 1983 { 1984 $buffer = ''; 1985 1986 if (!empty($this->data)) { 1987 if (is_int($this->dataName)) { 1988 $buffer .= sprintf(' with data set #%d', $this->dataName); 1989 } else { 1990 $buffer .= sprintf(' with data set "%s"', $this->dataName); 1991 } 1992 1993 $exporter = new Exporter; 1994 1995 if ($includeData) { 1996 $buffer .= sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data)); 1997 } 1998 } 1999 2000 return $buffer; 2001 } 2002 2003 /** 2004 * Gets the data set of a TestCase. 2005 * 2006 * @return array 2007 */ 2008 protected function getProvidedData() 2009 { 2010 return $this->data; 2011 } 2012 2013 /** 2014 * Creates a default TestResult object. 2015 * 2016 * @return PHPUnit_Framework_TestResult 2017 */ 2018 protected function createResult() 2019 { 2020 return new PHPUnit_Framework_TestResult; 2021 } 2022 2023 protected function handleDependencies() 2024 { 2025 if (!empty($this->dependencies) && !$this->inIsolation) { 2026 $className = get_class($this); 2027 $passed = $this->result->passed(); 2028 $passedKeys = array_keys($passed); 2029 $numKeys = count($passedKeys); 2030 2031 for ($i = 0; $i < $numKeys; $i++) { 2032 $pos = strpos($passedKeys[$i], ' with data set'); 2033 2034 if ($pos !== false) { 2035 $passedKeys[$i] = substr($passedKeys[$i], 0, $pos); 2036 } 2037 } 2038 2039 $passedKeys = array_flip(array_unique($passedKeys)); 2040 2041 foreach ($this->dependencies as $dependency) { 2042 $clone = false; 2043 2044 if (strpos($dependency, 'clone ') === 0) { 2045 $clone = true; 2046 $dependency = substr($dependency, strlen('clone ')); 2047 } elseif (strpos($dependency, '!clone ') === 0) { 2048 $clone = false; 2049 $dependency = substr($dependency, strlen('!clone ')); 2050 } 2051 2052 if (strpos($dependency, '::') === false) { 2053 $dependency = $className . '::' . $dependency; 2054 } 2055 2056 if (!isset($passedKeys[$dependency])) { 2057 $this->result->startTest($this); 2058 $this->result->addError( 2059 $this, 2060 new PHPUnit_Framework_SkippedTestError( 2061 sprintf( 2062 'This test depends on "%s" to pass.', 2063 $dependency 2064 ) 2065 ), 2066 0 2067 ); 2068 $this->result->endTest($this, 0); 2069 2070 return false; 2071 } 2072 2073 if (isset($passed[$dependency])) { 2074 if ($passed[$dependency]['size'] != PHPUnit_Util_Test::UNKNOWN && 2075 $this->getSize() != PHPUnit_Util_Test::UNKNOWN && 2076 $passed[$dependency]['size'] > $this->getSize()) { 2077 $this->result->addError( 2078 $this, 2079 new PHPUnit_Framework_SkippedTestError( 2080 'This test depends on a test that is larger than itself.' 2081 ), 2082 0 2083 ); 2084 2085 return false; 2086 } 2087 2088 if ($clone) { 2089 $deepCopy = new DeepCopy; 2090 $deepCopy->skipUncloneable(false); 2091 2092 $this->dependencyInput[$dependency] = $deepCopy->copy($passed[$dependency]['result']); 2093 } else { 2094 $this->dependencyInput[$dependency] = $passed[$dependency]['result']; 2095 } 2096 } else { 2097 $this->dependencyInput[$dependency] = null; 2098 } 2099 } 2100 } 2101 2102 return true; 2103 } 2104 2105 /** 2106 * This method is called before the first test of this test class is run. 2107 */ 2108 public static function setUpBeforeClass() 2109 { 2110 } 2111 2112 /** 2113 * Sets up the fixture, for example, open a network connection. 2114 * This method is called before a test is executed. 2115 */ 2116 protected function setUp() 2117 { 2118 } 2119 2120 /** 2121 * Performs assertions shared by all tests of a test case. 2122 * 2123 * This method is called before the execution of a test starts 2124 * and after setUp() is called. 2125 */ 2126 protected function assertPreConditions() 2127 { 2128 } 2129 2130 /** 2131 * Performs assertions shared by all tests of a test case. 2132 * 2133 * This method is called after the execution of a test ends 2134 * and before tearDown() is called. 2135 */ 2136 protected function assertPostConditions() 2137 { 2138 } 2139 2140 /** 2141 * Tears down the fixture, for example, close a network connection. 2142 * This method is called after a test is executed. 2143 */ 2144 protected function tearDown() 2145 { 2146 } 2147 2148 /** 2149 * This method is called after the last test of this test class is run. 2150 */ 2151 public static function tearDownAfterClass() 2152 { 2153 } 2154 2155 /** 2156 * This method is called when a test method did not execute successfully. 2157 * 2158 * @param Exception|Throwable $e 2159 * 2160 * @throws Exception|Throwable 2161 */ 2162 protected function onNotSuccessfulTest($e) 2163 { 2164 $expected = PHP_MAJOR_VERSION >= 7 ? 'Throwable' : 'Exception'; 2165 2166 if ($e instanceof $expected) { 2167 throw $e; 2168 } 2169 2170 throw PHPUnit_Util_InvalidArgumentHelper::factory( 2171 1, 2172 'Throwable or Exception' 2173 ); 2174 } 2175 2176 /** 2177 * Performs custom preparations on the process isolation template. 2178 * 2179 * @param Text_Template $template 2180 */ 2181 protected function prepareTemplate(Text_Template $template) 2182 { 2183 } 2184 2185 /** 2186 * Get the mock object generator, creating it if it doesn't exist. 2187 * 2188 * @return PHPUnit_Framework_MockObject_Generator 2189 */ 2190 protected function getMockObjectGenerator() 2191 { 2192 if (null === $this->mockObjectGenerator) { 2193 $this->mockObjectGenerator = new PHPUnit_Framework_MockObject_Generator; 2194 } 2195 2196 return $this->mockObjectGenerator; 2197 } 2198 2199 private function startOutputBuffering() 2200 { 2201 ob_start(); 2202 2203 $this->outputBufferingActive = true; 2204 $this->outputBufferingLevel = ob_get_level(); 2205 } 2206 2207 private function stopOutputBuffering() 2208 { 2209 if (ob_get_level() != $this->outputBufferingLevel) { 2210 while (ob_get_level() >= $this->outputBufferingLevel) { 2211 ob_end_clean(); 2212 } 2213 2214 throw new PHPUnit_Framework_RiskyTestError( 2215 'Test code or tested code did not (only) close its own output buffers' 2216 ); 2217 } 2218 2219 $output = ob_get_contents(); 2220 2221 if ($this->outputCallback === false) { 2222 $this->output = $output; 2223 } else { 2224 $this->output = call_user_func_array( 2225 $this->outputCallback, 2226 [$output] 2227 ); 2228 } 2229 2230 ob_end_clean(); 2231 2232 $this->outputBufferingActive = false; 2233 $this->outputBufferingLevel = ob_get_level(); 2234 } 2235 2236 private function snapshotGlobalState() 2237 { 2238 $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true; 2239 2240 if ($this->runTestInSeparateProcess || 2241 $this->inIsolation || 2242 (!$backupGlobals && !$this->backupStaticAttributes)) { 2243 return; 2244 } 2245 2246 $this->snapshot = $this->createGlobalStateSnapshot($backupGlobals); 2247 } 2248 2249 private function restoreGlobalState() 2250 { 2251 if (!$this->snapshot instanceof Snapshot) { 2252 return; 2253 } 2254 2255 $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true; 2256 2257 if ($this->beStrictAboutChangesToGlobalState) { 2258 try { 2259 $this->compareGlobalStateSnapshots( 2260 $this->snapshot, 2261 $this->createGlobalStateSnapshot($backupGlobals) 2262 ); 2263 } catch (PHPUnit_Framework_RiskyTestError $rte) { 2264 // Intentionally left empty 2265 } 2266 } 2267 2268 $restorer = new Restorer; 2269 2270 if ($backupGlobals) { 2271 $restorer->restoreGlobalVariables($this->snapshot); 2272 } 2273 2274 if ($this->backupStaticAttributes) { 2275 $restorer->restoreStaticAttributes($this->snapshot); 2276 } 2277 2278 $this->snapshot = null; 2279 2280 if (isset($rte)) { 2281 throw $rte; 2282 } 2283 } 2284 2285 /** 2286 * @param bool $backupGlobals 2287 * 2288 * @return Snapshot 2289 */ 2290 private function createGlobalStateSnapshot($backupGlobals) 2291 { 2292 $blacklist = new Blacklist; 2293 2294 foreach ($this->backupGlobalsBlacklist as $globalVariable) { 2295 $blacklist->addGlobalVariable($globalVariable); 2296 } 2297 2298 if (!defined('PHPUNIT_TESTSUITE')) { 2299 $blacklist->addClassNamePrefix('PHPUnit'); 2300 $blacklist->addClassNamePrefix('File_Iterator'); 2301 $blacklist->addClassNamePrefix('SebastianBergmann\CodeCoverage'); 2302 $blacklist->addClassNamePrefix('PHP_Invoker'); 2303 $blacklist->addClassNamePrefix('PHP_Timer'); 2304 $blacklist->addClassNamePrefix('PHP_Token'); 2305 $blacklist->addClassNamePrefix('Symfony'); 2306 $blacklist->addClassNamePrefix('Text_Template'); 2307 $blacklist->addClassNamePrefix('Doctrine\Instantiator'); 2308 $blacklist->addClassNamePrefix('Prophecy'); 2309 2310 foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) { 2311 foreach ($attributes as $attribute) { 2312 $blacklist->addStaticAttribute($class, $attribute); 2313 } 2314 } 2315 } 2316 2317 return new Snapshot( 2318 $blacklist, 2319 $backupGlobals, 2320 (bool) $this->backupStaticAttributes, 2321 false, 2322 false, 2323 false, 2324 false, 2325 false, 2326 false, 2327 false 2328 ); 2329 } 2330 2331 /** 2332 * @param Snapshot $before 2333 * @param Snapshot $after 2334 * 2335 * @throws PHPUnit_Framework_RiskyTestError 2336 */ 2337 private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after) 2338 { 2339 $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true; 2340 2341 if ($backupGlobals) { 2342 $this->compareGlobalStateSnapshotPart( 2343 $before->globalVariables(), 2344 $after->globalVariables(), 2345 "--- Global variables before the test\n+++ Global variables after the test\n" 2346 ); 2347 2348 $this->compareGlobalStateSnapshotPart( 2349 $before->superGlobalVariables(), 2350 $after->superGlobalVariables(), 2351 "--- Super-global variables before the test\n+++ Super-global variables after the test\n" 2352 ); 2353 } 2354 2355 if ($this->backupStaticAttributes) { 2356 $this->compareGlobalStateSnapshotPart( 2357 $before->staticAttributes(), 2358 $after->staticAttributes(), 2359 "--- Static attributes before the test\n+++ Static attributes after the test\n" 2360 ); 2361 } 2362 } 2363 2364 /** 2365 * @param array $before 2366 * @param array $after 2367 * @param string $header 2368 * 2369 * @throws PHPUnit_Framework_RiskyTestError 2370 */ 2371 private function compareGlobalStateSnapshotPart(array $before, array $after, $header) 2372 { 2373 if ($before != $after) { 2374 $differ = new Differ($header); 2375 $exporter = new Exporter; 2376 2377 $diff = $differ->diff( 2378 $exporter->export($before), 2379 $exporter->export($after) 2380 ); 2381 2382 throw new PHPUnit_Framework_RiskyTestError( 2383 $diff 2384 ); 2385 } 2386 } 2387 2388 /** 2389 * @return Prophecy\Prophet 2390 */ 2391 private function getProphet() 2392 { 2393 if ($this->prophet === null) { 2394 $this->prophet = new Prophet; 2395 } 2396 2397 return $this->prophet; 2398 } 2399 2400 /** 2401 * @param PHPUnit_Framework_MockObject_MockObject $mock 2402 * 2403 * @return bool 2404 */ 2405 private function shouldInvocationMockerBeReset(PHPUnit_Framework_MockObject_MockObject $mock) 2406 { 2407 $enumerator = new Enumerator; 2408 2409 foreach ($enumerator->enumerate($this->dependencyInput) as $object) { 2410 if ($mock === $object) { 2411 return false; 2412 } 2413 } 2414 2415 if (!is_array($this->testResult) && !is_object($this->testResult)) { 2416 return true; 2417 } 2418 2419 foreach ($enumerator->enumerate($this->testResult) as $object) { 2420 if ($mock === $object) { 2421 return false; 2422 } 2423 } 2424 2425 return true; 2426 } 2427 2428 /** 2429 * @param array $testArguments 2430 * @param array $originalTestArguments 2431 */ 2432 private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []) 2433 { 2434 if ($this->registerMockObjectsFromTestArgumentsRecursively) { 2435 $enumerator = new Enumerator; 2436 2437 foreach ($enumerator->enumerate($testArguments) as $object) { 2438 if ($object instanceof PHPUnit_Framework_MockObject_MockObject) { 2439 $this->registerMockObject($object); 2440 } 2441 } 2442 } else { 2443 foreach ($testArguments as $testArgument) { 2444 if ($testArgument instanceof PHPUnit_Framework_MockObject_MockObject) { 2445 if ($this->isCloneable($testArgument)) { 2446 $testArgument = clone $testArgument; 2447 } 2448 2449 $this->registerMockObject($testArgument); 2450 } elseif (is_array($testArgument) && !in_array($testArgument, $visited, true)) { 2451 $visited[] = $testArgument; 2452 2453 $this->registerMockObjectsFromTestArguments( 2454 $testArgument, 2455 $visited 2456 ); 2457 } 2458 } 2459 } 2460 } 2461 2462 private function setDoesNotPerformAssertionsFromAnnotation() 2463 { 2464 $annotations = $this->getAnnotations(); 2465 2466 if (isset($annotations['method']['doesNotPerformAssertions'])) { 2467 $this->doesNotPerformAssertions = true; 2468 } 2469 } 2470 2471 /** 2472 * @param PHPUnit_Framework_MockObject_MockObject $testArgument 2473 * 2474 * @return bool 2475 */ 2476 private function isCloneable(PHPUnit_Framework_MockObject_MockObject $testArgument) 2477 { 2478 $reflector = new ReflectionObject($testArgument); 2479 2480 if (!$reflector->isCloneable()) { 2481 return false; 2482 } 2483 2484 if ($reflector->hasMethod('__clone') && 2485 $reflector->getMethod('__clone')->isPublic()) { 2486 return true; 2487 } 2488 2489 return false; 2490 } 2491} 2492