Completed
Push — master ( 96d573...f9f049 )
by Ehsan
07:54
created

TestCase::runBare()   F

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 142
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 29
eloc 86
nc 4188672
nop 0
dl 0
loc 142
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PHPUnit\Framework;
12
13
use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint;
14
use PHPUnit\Framework\Constraint\ExceptionCode;
15
use PHPUnit\Framework\Constraint\ExceptionMessage;
16
use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression;
17
use PHPUnit_Framework_MockObject_Generator;
18
use PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
19
use PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex;
20
use PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount;
21
use PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
22
use PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount;
23
use PHPUnit_Framework_MockObject_Matcher_InvokedCount;
24
use PHPUnit_Framework_MockObject_MockBuilder;
25
use PHPUnit_Framework_MockObject_MockObject;
26
use PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls;
27
use PHPUnit_Framework_MockObject_Stub_Exception;
28
use PHPUnit_Framework_MockObject_Stub_Return;
29
use PHPUnit_Framework_MockObject_Stub_ReturnArgument;
30
use PHPUnit_Framework_MockObject_Stub_ReturnCallback;
31
use PHPUnit_Framework_MockObject_Stub_ReturnSelf;
32
use PHPUnit_Framework_MockObject_Stub_ReturnValueMap;
33
use PHPUnit\Runner\BaseTestRunner;
34
use PHPUnit\Runner\PhptTestCase;
35
use PHPUnit\Util\GlobalState;
36
use PHPUnit\Util\InvalidArgumentHelper;
37
use PHPUnit\Util\PHP\AbstractPhpProcess;
38
use Prophecy;
39
use ReflectionClass;
40
use ReflectionException;
41
use ReflectionObject;
42
use SebastianBergmann;
43
use SebastianBergmann\GlobalState\Snapshot;
44
use SebastianBergmann\GlobalState\Restorer;
45
use SebastianBergmann\GlobalState\Blacklist;
46
use SebastianBergmann\Diff\Differ;
47
use SebastianBergmann\Exporter\Exporter;
48
use SebastianBergmann\ObjectEnumerator\Enumerator;
49
use Prophecy\Exception\Prediction\PredictionException;
50
use Prophecy\Prophet;
51
use DeepCopy\DeepCopy;
52
use Text_Template;
53
use Throwable;
54
55
/**
56
 * A TestCase defines the fixture to run multiple tests.
57
 *
58
 * To define a TestCase
59
 *
60
 *   1) Implement a subclass of PHPUnit\Framework\TestCase.
61
 *   2) Define instance variables that store the state of the fixture.
62
 *   3) Initialize the fixture state by overriding setUp().
63
 *   4) Clean-up after a test by overriding tearDown().
64
 *
65
 * Each test runs in its own fixture so there can be no side effects
66
 * among test runs.
67
 *
68
 * Here is an example:
69
 *
70
 * <code>
71
 * <?php
72
 * class MathTest extends PHPUnit\Framework\TestCase
73
 * {
74
 *     public $value1;
75
 *     public $value2;
76
 *
77
 *     protected function setUp()
78
 *     {
79
 *         $this->value1 = 2;
80
 *         $this->value2 = 3;
81
 *     }
82
 * }
83
 * ?>
84
 * </code>
85
 *
86
 * For each test implement a method which interacts with the fixture.
87
 * Verify the expected results with assertions specified by calling
88
 * assert with a boolean.
89
 *
90
 * <code>
91
 * <?php
92
 * public function testPass()
93
 * {
94
 *     $this->assertTrue($this->value1 + $this->value2 == 5);
95
 * }
96
 * ?>
97
 * </code>
98
 */
99
abstract class TestCase extends Assert implements Test, SelfDescribing
100
{
101
    /**
102
     * Enable or disable the backup and restoration of the $GLOBALS array.
103
     * Overwrite this attribute in a child class of TestCase.
104
     * Setting this attribute in setUp() has no effect!
105
     *
106
     * @var bool
107
     */
108
    protected $backupGlobals;
109
110
    /**
111
     * @var array
112
     */
113
    protected $backupGlobalsBlacklist = [];
114
115
    /**
116
     * Enable or disable the backup and restoration of static attributes.
117
     * Overwrite this attribute in a child class of TestCase.
118
     * Setting this attribute in setUp() has no effect!
119
     *
120
     * @var bool
121
     */
122
    protected $backupStaticAttributes;
123
124
    /**
125
     * @var array
126
     */
127
    protected $backupStaticAttributesBlacklist = [];
128
129
    /**
130
     * Whether or not this test is to be run in a separate PHP process.
131
     *
132
     * @var bool
133
     */
134
    protected $runTestInSeparateProcess;
135
136
    /**
137
     * Whether or not this test should preserve the global state when
138
     * running in a separate PHP process.
139
     *
140
     * @var bool
141
     */
142
    protected $preserveGlobalState = true;
143
144
    /**
145
     * Whether or not this test is running in a separate PHP process.
146
     *
147
     * @var bool
148
     */
149
    private $inIsolation = false;
150
151
    /**
152
     * @var array
153
     */
154
    private $data;
155
156
    /**
157
     * @var string
158
     */
159
    private $dataName;
160
161
    /**
162
     * @var bool
163
     */
164
    private $useErrorHandler;
165
166
    /**
167
     * The name of the expected Exception.
168
     *
169
     * @var string
170
     */
171
    private $expectedException;
172
173
    /**
174
     * The message of the expected Exception.
175
     *
176
     * @var string
177
     */
178
    private $expectedExceptionMessage = '';
179
180
    /**
181
     * The regex pattern to validate the expected Exception message.
182
     *
183
     * @var string
184
     */
185
    private $expectedExceptionMessageRegExp = '';
186
187
    /**
188
     * The code of the expected Exception.
189
     *
190
     * @var int|string
191
     */
192
    private $expectedExceptionCode;
193
194
    /**
195
     * The name of the test case.
196
     *
197
     * @var string
198
     */
199
    private $name;
200
201
    /**
202
     * @var array
203
     */
204
    private $dependencies = [];
205
206
    /**
207
     * @var array
208
     */
209
    private $dependencyInput = [];
210
211
    /**
212
     * @var array
213
     */
214
    private $iniSettings = [];
215
216
    /**
217
     * @var array
218
     */
219
    private $locale = [];
220
221
    /**
222
     * @var array
223
     */
224
    private $mockObjects = [];
225
226
    /**
227
     * @var array
228
     */
229
    private $mockObjectGenerator;
230
231
    /**
232
     * @var int
233
     */
234
    private $status;
235
236
    /**
237
     * @var string
238
     */
239
    private $statusMessage = '';
240
241
    /**
242
     * @var int
243
     */
244
    private $numAssertions = 0;
245
246
    /**
247
     * @var TestResult
248
     */
249
    private $result;
250
251
    /**
252
     * @var mixed
253
     */
254
    private $testResult;
255
256
    /**
257
     * @var string
258
     */
259
    private $output = '';
260
261
    /**
262
     * @var string
263
     */
264
    private $outputExpectedRegex;
265
266
    /**
267
     * @var string
268
     */
269
    private $outputExpectedString;
270
271
    /**
272
     * @var mixed
273
     */
274
    private $outputCallback = false;
275
276
    /**
277
     * @var bool
278
     */
279
    private $outputBufferingActive = false;
280
281
    /**
282
     * @var int
283
     */
284
    private $outputBufferingLevel;
285
286
    /**
287
     * @var SebastianBergmann\GlobalState\Snapshot
288
     */
289
    private $snapshot;
290
291
    /**
292
     * @var Prophecy\Prophet
293
     */
294
    private $prophet;
295
296
    /**
297
     * @var bool
298
     */
299
    private $beStrictAboutChangesToGlobalState = false;
300
301
    /**
302
     * @var bool
303
     */
304
    private $registerMockObjectsFromTestArgumentsRecursively = false;
305
306
    /**
307
     * @var string[]
308
     */
309
    private $warnings = [];
310
311
    /**
312
     * @var array
313
     */
314
    private $groups = [];
315
316
    /**
317
     * @var bool
318
     */
319
    private $doesNotPerformAssertions = false;
320
321
    /**
322
     * Constructs a test case with the given name.
323
     *
324
     * @param string $name
325
     * @param array  $data
326
     * @param string $dataName
327
     */
328
    public function __construct($name = null, array $data = [], $dataName = '')
329
    {
330
        if ($name !== null) {
331
            $this->setName($name);
332
        }
333
334
        $this->data     = $data;
335
        $this->dataName = $dataName;
336
    }
337
338
    /**
339
     * Returns a string representation of the test case.
340
     *
341
     * @return string
342
     */
343
    public function toString()
344
    {
345
        $class = new ReflectionClass($this);
346
347
        $buffer = \sprintf(
348
            '%s::%s',
349
            $class->name,
350
            $this->getName(false)
351
        );
352
353
        return $buffer . $this->getDataSetAsString();
354
    }
355
356
    /**
357
     * Counts the number of test cases executed by run(TestResult result).
358
     *
359
     * @return int
360
     */
361
    public function count()
362
    {
363
        return 1;
364
    }
365
366
    public function getGroups()
367
    {
368
        return $this->groups;
369
    }
370
371
    /**
372
     * @param array $groups
373
     */
374
    public function setGroups(array $groups)
375
    {
376
        $this->groups = $groups;
377
    }
378
379
    /**
380
     * Returns the annotations for this test.
381
     *
382
     * @return array
383
     */
384
    public function getAnnotations()
385
    {
386
        return \PHPUnit\Util\Test::parseTestMethodAnnotations(
387
            \get_class($this),
388
            $this->name
389
        );
390
    }
391
392
    /**
393
     * Gets the name of a TestCase.
394
     *
395
     * @param bool $withDataSet
396
     *
397
     * @return string
398
     */
399
    public function getName($withDataSet = true)
400
    {
401
        if ($withDataSet) {
402
            return $this->name . $this->getDataSetAsString(false);
403
        }
404
405
        return $this->name;
406
    }
407
408
    /**
409
     * Returns the size of the test.
410
     *
411
     * @return int
412
     */
413
    public function getSize()
414
    {
415
        return \PHPUnit\Util\Test::getSize(
416
            \get_class($this),
417
            $this->getName(false)
418
        );
419
    }
420
421
    /**
422
     * @return bool
423
     */
424
    public function hasSize()
425
    {
426
        return $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN;
427
    }
428
429
    /**
430
     * @return bool
431
     */
432
    public function isSmall()
433
    {
434
        return $this->getSize() === \PHPUnit\Util\Test::SMALL;
435
    }
436
437
    /**
438
     * @return bool
439
     */
440
    public function isMedium()
441
    {
442
        return $this->getSize() === \PHPUnit\Util\Test::MEDIUM;
443
    }
444
445
    /**
446
     * @return bool
447
     */
448
    public function isLarge()
449
    {
450
        return $this->getSize() === \PHPUnit\Util\Test::LARGE;
451
    }
452
453
    /**
454
     * @return string
455
     */
456
    public function getActualOutput()
457
    {
458
        if (!$this->outputBufferingActive) {
459
            return $this->output;
460
        }
461
462
        return \ob_get_contents();
463
    }
464
465
    /**
466
     * @return bool
467
     */
468
    public function hasOutput()
469
    {
470
        if (\strlen($this->output) === 0) {
471
            return false;
472
        }
473
474
        if ($this->hasExpectationOnOutput()) {
475
            return false;
476
        }
477
478
        return true;
479
    }
480
481
    /**
482
     * @return bool
483
     */
484
    public function doesNotPerformAssertions()
485
    {
486
        return $this->doesNotPerformAssertions;
487
    }
488
489
    /**
490
     * @param string $expectedRegex
491
     *
492
     * @throws Exception
493
     */
494
    public function expectOutputRegex($expectedRegex)
495
    {
496
        if ($this->outputExpectedString !== null) {
497
            throw new Exception;
498
        }
499
500
        if (\is_string($expectedRegex) || \is_null($expectedRegex)) {
501
            $this->outputExpectedRegex = $expectedRegex;
502
        }
503
    }
504
505
    /**
506
     * @param string $expectedString
507
     */
508
    public function expectOutputString($expectedString)
509
    {
510
        if ($this->outputExpectedRegex !== null) {
511
            throw new Exception;
512
        }
513
514
        if (\is_string($expectedString) || \is_null($expectedString)) {
515
            $this->outputExpectedString = $expectedString;
516
        }
517
    }
518
519
    /**
520
     * @return bool
521
     */
522
    public function hasExpectationOnOutput()
523
    {
524
        return \is_string($this->outputExpectedString) || \is_string($this->outputExpectedRegex);
525
    }
526
527
    /**
528
     * @return string
529
     */
530
    public function getExpectedException()
531
    {
532
        return $this->expectedException;
533
    }
534
535
    /**
536
     * @return int|string
537
     */
538
    public function getExpectedExceptionCode()
539
    {
540
        return $this->expectedExceptionCode;
541
    }
542
543
    /**
544
     * @return string
545
     */
546
    public function getExpectedExceptionMessage()
547
    {
548
        return $this->expectedExceptionMessage;
549
    }
550
551
    /**
552
     * @param string $exception
553
     */
554
    public function expectException($exception)
555
    {
556
        if (!\is_string($exception)) {
557
            throw InvalidArgumentHelper::factory(1, 'string');
558
        }
559
560
        $this->expectedException = $exception;
561
    }
562
563
    /**
564
     * @param int|string $code
565
     *
566
     * @throws Exception
567
     */
568
    public function expectExceptionCode($code)
569
    {
570
        if (!$this->expectedException) {
571
            $this->expectedException = \Exception::class;
572
        }
573
574
        if (!\is_int($code) && !\is_string($code)) {
575
            throw InvalidArgumentHelper::factory(1, 'integer or string');
576
        }
577
578
        $this->expectedExceptionCode = $code;
579
    }
580
581
    /**
582
     * @param string $message
583
     *
584
     * @throws Exception
585
     */
586
    public function expectExceptionMessage($message)
587
    {
588
        if (!$this->expectedException) {
589
            $this->expectedException = \Exception::class;
590
        }
591
592
        if (!\is_string($message)) {
593
            throw InvalidArgumentHelper::factory(1, 'string');
594
        }
595
596
        $this->expectedExceptionMessage = $message;
597
    }
598
599
    /**
600
     * @param string $messageRegExp
601
     *
602
     * @throws Exception
603
     */
604
    public function expectExceptionMessageRegExp($messageRegExp)
605
    {
606
        if (!\is_string($messageRegExp)) {
607
            throw InvalidArgumentHelper::factory(1, 'string');
608
        }
609
610
        $this->expectedExceptionMessageRegExp = $messageRegExp;
611
    }
612
613
    /**
614
     * @param bool $flag
615
     */
616
    public function setRegisterMockObjectsFromTestArgumentsRecursively($flag)
617
    {
618
        if (!\is_bool($flag)) {
619
            throw InvalidArgumentHelper::factory(1, 'boolean');
620
        }
621
622
        $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
623
    }
624
625
    protected function setExpectedExceptionFromAnnotation()
626
    {
627
        try {
628
            $expectedException = \PHPUnit\Util\Test::getExpectedException(
629
                \get_class($this),
630
                $this->name
631
            );
632
633
            if ($expectedException !== false) {
634
                $this->expectException($expectedException['class']);
635
636
                if ($expectedException['code'] !== null) {
637
                    $this->expectExceptionCode($expectedException['code']);
638
                }
639
640
                if ($expectedException['message'] !== '') {
641
                    $this->expectExceptionMessage($expectedException['message']);
642
                } elseif ($expectedException['message_regex'] !== '') {
643
                    $this->expectExceptionMessageRegExp($expectedException['message_regex']);
644
                }
645
            }
646
        } catch (ReflectionException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
647
        }
648
    }
649
650
    /**
651
     * @param bool $useErrorHandler
652
     */
653
    public function setUseErrorHandler($useErrorHandler)
654
    {
655
        $this->useErrorHandler = $useErrorHandler;
656
    }
657
658
    protected function setUseErrorHandlerFromAnnotation()
659
    {
660
        try {
661
            $useErrorHandler = \PHPUnit\Util\Test::getErrorHandlerSettings(
662
                \get_class($this),
663
                $this->name
664
            );
665
666
            if ($useErrorHandler !== null) {
667
                $this->setUseErrorHandler($useErrorHandler);
668
            }
669
        } catch (ReflectionException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
670
        }
671
    }
672
673
    protected function checkRequirements()
674
    {
675
        if (!$this->name || !\method_exists($this, $this->name)) {
676
            return;
677
        }
678
679
        $missingRequirements = \PHPUnit\Util\Test::getMissingRequirements(
680
            \get_class($this),
681
            $this->name
682
        );
683
684
        if (!empty($missingRequirements)) {
685
            $this->markTestSkipped(\implode(PHP_EOL, $missingRequirements));
686
        }
687
    }
688
689
    /**
690
     * Returns the status of this test.
691
     *
692
     * @return int
693
     */
694
    public function getStatus()
695
    {
696
        return $this->status;
697
    }
698
699
    public function markAsRisky()
700
    {
701
        $this->status = BaseTestRunner::STATUS_RISKY;
702
    }
703
704
    /**
705
     * Returns the status message of this test.
706
     *
707
     * @return string
708
     */
709
    public function getStatusMessage()
710
    {
711
        return $this->statusMessage;
712
    }
713
714
    /**
715
     * Returns whether or not this test has failed.
716
     *
717
     * @return bool
718
     */
719
    public function hasFailed()
720
    {
721
        $status = $this->getStatus();
722
723
        return $status == BaseTestRunner::STATUS_FAILURE ||
724
            $status == BaseTestRunner::STATUS_ERROR;
725
    }
726
727
    /**
728
     * Runs the test case and collects the results in a TestResult object.
729
     * If no TestResult object is passed a new one will be created.
730
     *
731
     * @param TestResult $result
732
     *
733
     * @return TestResult
734
     *
735
     * @throws Exception
736
     */
737
    public function run(TestResult $result = null)
738
    {
739
        if ($result === null) {
740
            $result = $this->createResult();
741
        }
742
743
        if (!$this instanceof WarningTestCase) {
744
            $this->setTestResultObject($result);
745
            $this->setUseErrorHandlerFromAnnotation();
746
        }
747
748
        if ($this->useErrorHandler !== null) {
749
            $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions();
750
            $result->convertErrorsToExceptions($this->useErrorHandler);
751
        }
752
753
        if (!$this instanceof WarningTestCase &&
754
            !$this instanceof SkippedTestCase &&
755
            !$this->handleDependencies()) {
756
            return;
757
        }
758
759
        if ($this->runTestInSeparateProcess === true &&
760
            $this->inIsolation !== true &&
761
            !$this instanceof PhptTestCase) {
762
            $class = new ReflectionClass($this);
763
764
            $template = new Text_Template(
765
                __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl'
766
            );
767
768
            if ($this->preserveGlobalState) {
769
                $constants     = GlobalState::getConstantsAsString();
770
                $globals       = GlobalState::getGlobalsAsString();
771
                $includedFiles = GlobalState::getIncludedFilesAsString();
772
                $iniSettings   = GlobalState::getIniSettingsAsString();
773
            } else {
774
                $constants = '';
775
                if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
776
                    $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n";
777
                } else {
778
                    $globals = '';
779
                }
780
                $includedFiles = '';
781
                $iniSettings   = '';
782
            }
783
784
            $coverage                                   = $result->getCollectCodeCoverageInformation() ? 'true' : 'false';
785
            $isStrictAboutTestsThatDoNotTestAnything    = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false';
786
            $isStrictAboutOutputDuringTests             = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false';
787
            $enforcesTimeLimit                          = $result->enforcesTimeLimit() ? 'true' : 'false';
788
            $isStrictAboutTodoAnnotatedTests            = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false';
789
            $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false';
790
791
            if (\defined('PHPUNIT_COMPOSER_INSTALL')) {
792
                $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, true);
793
            } else {
794
                $composerAutoload = '\'\'';
795
            }
796
797
            if (\defined('__PHPUNIT_PHAR__')) {
798
                $phar = \var_export(__PHPUNIT_PHAR__, true);
799
            } else {
800
                $phar = '\'\'';
801
            }
802
803
            if ($result->getCodeCoverage()) {
804
                $codeCoverageFilter = $result->getCodeCoverage()->filter();
805
            } else {
806
                $codeCoverageFilter = null;
807
            }
808
809
            $data               = \var_export(\serialize($this->data), true);
810
            $dataName           = \var_export($this->dataName, true);
811
            $dependencyInput    = \var_export(\serialize($this->dependencyInput), true);
812
            $includePath        = \var_export(\get_include_path(), true);
813
            $codeCoverageFilter = \var_export(\serialize($codeCoverageFilter), true);
814
            // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
815
            // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
816
            $data               = "'." . $data . ".'";
817
            $dataName           = "'.(" . $dataName . ").'";
818
            $dependencyInput    = "'." . $dependencyInput . ".'";
819
            $includePath        = "'." . $includePath . ".'";
820
            $codeCoverageFilter = "'." . $codeCoverageFilter . ".'";
821
822
            $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';
823
824
            $template->setVar(
825
                [
826
                    'composerAutoload'                           => $composerAutoload,
827
                    'phar'                                       => $phar,
828
                    'filename'                                   => $class->getFileName(),
829
                    'className'                                  => $class->getName(),
0 ignored issues
show
Bug introduced by
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
830
                    'methodName'                                 => $this->name,
831
                    'collectCodeCoverageInformation'             => $coverage,
832
                    'data'                                       => $data,
833
                    'dataName'                                   => $dataName,
834
                    'dependencyInput'                            => $dependencyInput,
835
                    'constants'                                  => $constants,
836
                    'globals'                                    => $globals,
837
                    'include_path'                               => $includePath,
838
                    'included_files'                             => $includedFiles,
839
                    'iniSettings'                                => $iniSettings,
840
                    'isStrictAboutTestsThatDoNotTestAnything'    => $isStrictAboutTestsThatDoNotTestAnything,
841
                    'isStrictAboutOutputDuringTests'             => $isStrictAboutOutputDuringTests,
842
                    'enforcesTimeLimit'                          => $enforcesTimeLimit,
843
                    'isStrictAboutTodoAnnotatedTests'            => $isStrictAboutTodoAnnotatedTests,
844
                    'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests,
845
                    'codeCoverageFilter'                         => $codeCoverageFilter,
846
                    'configurationFilePath'                      => $configurationFilePath
847
                ]
848
            );
849
850
            $this->prepareTemplate($template);
851
852
            $php = AbstractPhpProcess::factory();
853
            $php->runTestJob($template->render(), $this, $result);
854
        } else {
855
            $result->run($this);
856
        }
857
858
        if ($this->useErrorHandler !== null) {
859
            $result->convertErrorsToExceptions($oldErrorHandlerSetting);
0 ignored issues
show
Bug introduced by
The variable $oldErrorHandlerSetting does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
860
        }
861
862
        $this->result = null;
863
864
        return $result;
865
    }
866
867
    /**
868
     * Runs the bare test sequence.
869
     */
870
    public function runBare()
871
    {
872
        $this->numAssertions = 0;
873
874
        $this->snapshotGlobalState();
875
        $this->startOutputBuffering();
876
        \clearstatcache();
877
        $currentWorkingDirectory = \getcwd();
878
879
        $hookMethods = \PHPUnit\Util\Test::getHookMethods(\get_class($this));
880
881
        try {
882
            $hasMetRequirements = false;
883
            $this->checkRequirements();
884
            $hasMetRequirements = true;
885
886
            if ($this->inIsolation) {
887
                foreach ($hookMethods['beforeClass'] as $method) {
888
                    $this->$method();
889
                }
890
            }
891
892
            $this->setExpectedExceptionFromAnnotation();
893
            $this->setDoesNotPerformAssertionsFromAnnotation();
894
895
            foreach ($hookMethods['before'] as $method) {
896
                $this->$method();
897
            }
898
899
            $this->assertPreConditions();
900
            $this->testResult = $this->runTest();
901
            $this->verifyMockObjects();
902
            $this->assertPostConditions();
903
904
            if (!empty($this->warnings)) {
905
                throw new Warning(
906
                    \implode(
907
                        "\n",
908
                        \array_unique($this->warnings)
909
                    )
910
                );
911
            }
912
913
            $this->status = BaseTestRunner::STATUS_PASSED;
914
        } catch (IncompleteTest $e) {
915
            $this->status        = BaseTestRunner::STATUS_INCOMPLETE;
916
            $this->statusMessage = $e->getMessage();
917
        } catch (SkippedTest $e) {
918
            $this->status        = BaseTestRunner::STATUS_SKIPPED;
919
            $this->statusMessage = $e->getMessage();
920
        } catch (Warning $e) {
921
            $this->status        = BaseTestRunner::STATUS_WARNING;
922
            $this->statusMessage = $e->getMessage();
923
        } catch (AssertionFailedError $e) {
924
            $this->status        = BaseTestRunner::STATUS_FAILURE;
925
            $this->statusMessage = $e->getMessage();
926
        } catch (PredictionException $e) {
927
            $this->status        = BaseTestRunner::STATUS_FAILURE;
928
            $this->statusMessage = $e->getMessage();
929
        } catch (Throwable $_e) {
930
            $e = $_e;
931
        }
932
933
        if (isset($_e)) {
934
            $this->status        = BaseTestRunner::STATUS_ERROR;
935
            $this->statusMessage = $_e->getMessage();
936
        }
937
938
        // Clean up the mock objects.
939
        $this->mockObjects = [];
940
        $this->prophet     = null;
941
942
        // Tear down the fixture. An exception raised in tearDown() will be
943
        // caught and passed on when no exception was raised before.
944
        try {
945
            if ($hasMetRequirements) {
946
                foreach ($hookMethods['after'] as $method) {
947
                    $this->$method();
948
                }
949
950
                if ($this->inIsolation) {
951
                    foreach ($hookMethods['afterClass'] as $method) {
952
                        $this->$method();
953
                    }
954
                }
955
            }
956
        } catch (Throwable $_e) {
957
            if (!isset($e)) {
958
                $e = $_e;
959
            }
960
        }
961
962
        try {
963
            $this->stopOutputBuffering();
964
        } catch (RiskyTestError $_e) {
965
            if (!isset($e)) {
966
                $e = $_e;
967
            }
968
        }
969
970
        \clearstatcache();
971
972
        if ($currentWorkingDirectory != \getcwd()) {
973
            \chdir($currentWorkingDirectory);
974
        }
975
976
        $this->restoreGlobalState();
977
978
        // Clean up INI settings.
979
        foreach ($this->iniSettings as $varName => $oldValue) {
980
            \ini_set($varName, $oldValue);
981
        }
982
983
        $this->iniSettings = [];
984
985
        // Clean up locale settings.
986
        foreach ($this->locale as $category => $locale) {
987
            \setlocale($category, $locale);
988
        }
989
990
        // Perform assertion on output.
991
        if (!isset($e)) {
992
            try {
993
                if ($this->outputExpectedRegex !== null) {
994
                    $this->assertRegExp($this->outputExpectedRegex, $this->output);
995
                } elseif ($this->outputExpectedString !== null) {
996
                    $this->assertEquals($this->outputExpectedString, $this->output);
997
                }
998
            } catch (Throwable $_e) {
999
                $e = $_e;
1000
            }
1001
        }
1002
1003
        // Workaround for missing "finally".
1004
        if (isset($e)) {
1005
            if ($e instanceof PredictionException) {
1006
                $e = new AssertionFailedError($e->getMessage());
1007
            }
1008
1009
            $this->onNotSuccessfulTest($e);
0 ignored issues
show
Bug introduced by
It seems like $e can also be of type object<PHPUnit\Framework\IncompleteTest> or object<PHPUnit\Framework\SkippedTest>; however, PHPUnit\Framework\TestCase::onNotSuccessfulTest() does only seem to accept object<Throwable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1010
        }
1011
    }
1012
1013
    /**
1014
     * Override to run the test and assert its state.
1015
     *
1016
     * @return mixed
1017
     *
1018
     * @throws Exception|Exception
1019
     * @throws Exception
1020
     */
1021
    protected function runTest()
1022
    {
1023
        if ($this->name === null) {
1024
            throw new Exception(
1025
                'PHPUnit\Framework\TestCase::$name must not be null.'
1026
            );
1027
        }
1028
1029
        try {
1030
            $class  = new ReflectionClass($this);
1031
            $method = $class->getMethod($this->name);
1032
        } catch (ReflectionException $e) {
1033
            $this->fail($e->getMessage());
1034
        }
1035
1036
        $testArguments = \array_merge($this->data, $this->dependencyInput);
1037
1038
        $this->registerMockObjectsFromTestArguments($testArguments);
1039
1040
        try {
1041
            $testResult = $method->invokeArgs($this, $testArguments);
0 ignored issues
show
Bug introduced by
The variable $method does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1042
        } catch (Throwable $_e) {
1043
            $e = $_e;
1044
        }
1045
1046
        if (isset($e)) {
1047
            $checkException = false;
1048
1049
            if (!($e instanceof SkippedTestError) && \is_string($this->expectedException)) {
1050
                $checkException = true;
1051
1052
                if ($e instanceof Exception) {
1053
                    $checkException = false;
1054
                }
1055
1056
                $reflector = new ReflectionClass($this->expectedException);
1057
1058
                if ($this->expectedException === 'PHPUnit\Framework\Exception' ||
1059
                    $this->expectedException === '\PHPUnit\Framework\Exception' ||
1060
                    $reflector->isSubclassOf('PHPUnit\Framework\Exception')) {
1061
                    $checkException = true;
1062
                }
1063
            }
1064
1065
            if ($checkException) {
1066
                $this->assertThat(
1067
                    $e,
1068
                    new ExceptionConstraint(
1069
                        $this->expectedException
1070
                    )
1071
                );
1072
1073
                if (\is_string($this->expectedExceptionMessage) &&
1074
                    !empty($this->expectedExceptionMessage)) {
1075
                    $this->assertThat(
1076
                        $e,
1077
                        new ExceptionMessage(
1078
                            $this->expectedExceptionMessage
1079
                        )
1080
                    );
1081
                }
1082
1083
                if (\is_string($this->expectedExceptionMessageRegExp) &&
1084
                    !empty($this->expectedExceptionMessageRegExp)) {
1085
                    $this->assertThat(
1086
                        $e,
1087
                        new ExceptionMessageRegularExpression(
1088
                            $this->expectedExceptionMessageRegExp
1089
                        )
1090
                    );
1091
                }
1092
1093
                if ($this->expectedExceptionCode !== null) {
1094
                    $this->assertThat(
1095
                        $e,
1096
                        new ExceptionCode(
1097
                            $this->expectedExceptionCode
1098
                        )
1099
                    );
1100
                }
1101
1102
                return;
1103
            }
1104
1105
            throw $e;
1106
        }
1107
1108
        if ($this->expectedException !== null) {
1109
            $this->assertThat(
1110
                null,
1111
                new ExceptionConstraint(
1112
                    $this->expectedException
1113
                )
1114
            );
1115
        }
1116
1117
        return $testResult;
1118
    }
1119
1120
    /**
1121
     * Verifies the mock object expectations.
1122
     */
1123
    protected function verifyMockObjects()
1124
    {
1125
        foreach ($this->mockObjects as $mockObject) {
1126
            if ($mockObject->__phpunit_hasMatchers()) {
1127
                $this->numAssertions++;
1128
            }
1129
1130
            $mockObject->__phpunit_verify(
1131
                $this->shouldInvocationMockerBeReset($mockObject)
1132
            );
1133
        }
1134
1135
        if ($this->prophet !== null) {
1136
            try {
1137
                $this->prophet->checkPredictions();
1138
            } catch (Throwable $t) {
1139
                /* Intentionally left empty */
1140
            }
1141
1142
            foreach ($this->prophet->getProphecies() as $objectProphecy) {
1143
                foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) {
1144
                    foreach ($methodProphecies as $methodProphecy) {
0 ignored issues
show
Bug introduced by
The expression $methodProphecies of type object<Prophecy\Prophecy\MethodProphecy> is not traversable.
Loading history...
1145
                        $this->numAssertions += \count($methodProphecy->getCheckedPredictions());
1146
                    }
1147
                }
1148
            }
1149
1150
            if (isset($t)) {
1151
                throw $t;
1152
            }
1153
        }
1154
    }
1155
1156
    /**
1157
     * Sets the name of a TestCase.
1158
     *
1159
     * @param  string
1160
     */
1161
    public function setName($name)
1162
    {
1163
        $this->name = $name;
1164
    }
1165
1166
    /**
1167
     * Sets the dependencies of a TestCase.
1168
     *
1169
     * @param array $dependencies
1170
     */
1171
    public function setDependencies(array $dependencies)
1172
    {
1173
        $this->dependencies = $dependencies;
1174
    }
1175
1176
    /**
1177
     * Returns true if the tests has dependencies
1178
     *
1179
     * @return bool
1180
     */
1181
    public function hasDependencies()
1182
    {
1183
        return \count($this->dependencies) > 0;
1184
    }
1185
1186
    /**
1187
     * Sets
1188
     *
1189
     * @param array $dependencyInput
1190
     */
1191
    public function setDependencyInput(array $dependencyInput)
1192
    {
1193
        $this->dependencyInput = $dependencyInput;
1194
    }
1195
1196
    /**
1197
     * @param bool $beStrictAboutChangesToGlobalState
1198
     */
1199
    public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState)
1200
    {
1201
        $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
1202
    }
1203
1204
    /**
1205
     * Calling this method in setUp() has no effect!
1206
     *
1207
     * @param bool $backupGlobals
1208
     */
1209
    public function setBackupGlobals($backupGlobals)
1210
    {
1211
        if (\is_null($this->backupGlobals) && \is_bool($backupGlobals)) {
1212
            $this->backupGlobals = $backupGlobals;
1213
        }
1214
    }
1215
1216
    /**
1217
     * Calling this method in setUp() has no effect!
1218
     *
1219
     * @param bool $backupStaticAttributes
1220
     */
1221
    public function setBackupStaticAttributes($backupStaticAttributes)
1222
    {
1223
        if (\is_null($this->backupStaticAttributes) &&
1224
            \is_bool($backupStaticAttributes)) {
1225
            $this->backupStaticAttributes = $backupStaticAttributes;
1226
        }
1227
    }
1228
1229
    /**
1230
     * @param bool $runTestInSeparateProcess
1231
     *
1232
     * @throws Exception
1233
     */
1234
    public function setRunTestInSeparateProcess($runTestInSeparateProcess)
1235
    {
1236
        if (\is_bool($runTestInSeparateProcess)) {
1237
            if ($this->runTestInSeparateProcess === null) {
1238
                $this->runTestInSeparateProcess = $runTestInSeparateProcess;
1239
            }
1240
        } else {
1241
            throw InvalidArgumentHelper::factory(1, 'boolean');
1242
        }
1243
    }
1244
1245
    /**
1246
     * @param bool $preserveGlobalState
1247
     *
1248
     * @throws Exception
1249
     */
1250
    public function setPreserveGlobalState($preserveGlobalState)
1251
    {
1252
        if (\is_bool($preserveGlobalState)) {
1253
            $this->preserveGlobalState = $preserveGlobalState;
1254
        } else {
1255
            throw InvalidArgumentHelper::factory(1, 'boolean');
1256
        }
1257
    }
1258
1259
    /**
1260
     * @param bool $inIsolation
1261
     *
1262
     * @throws Exception
1263
     */
1264
    public function setInIsolation($inIsolation)
1265
    {
1266
        if (\is_bool($inIsolation)) {
1267
            $this->inIsolation = $inIsolation;
1268
        } else {
1269
            throw InvalidArgumentHelper::factory(1, 'boolean');
1270
        }
1271
    }
1272
1273
    /**
1274
     * @return bool
1275
     */
1276
    public function isInIsolation()
1277
    {
1278
        return $this->inIsolation;
1279
    }
1280
1281
    /**
1282
     * @return mixed
1283
     */
1284
    public function getResult()
1285
    {
1286
        return $this->testResult;
1287
    }
1288
1289
    /**
1290
     * @param mixed $result
1291
     */
1292
    public function setResult($result)
1293
    {
1294
        $this->testResult = $result;
1295
    }
1296
1297
    /**
1298
     * @param callable $callback
1299
     *
1300
     * @throws Exception
1301
     */
1302
    public function setOutputCallback($callback)
1303
    {
1304
        if (!\is_callable($callback)) {
1305
            throw InvalidArgumentHelper::factory(1, 'callback');
1306
        }
1307
1308
        $this->outputCallback = $callback;
1309
    }
1310
1311
    /**
1312
     * @return TestResult
1313
     */
1314
    public function getTestResultObject()
1315
    {
1316
        return $this->result;
1317
    }
1318
1319
    /**
1320
     * @param TestResult $result
1321
     */
1322
    public function setTestResultObject(TestResult $result)
1323
    {
1324
        $this->result = $result;
1325
    }
1326
1327
    /**
1328
     * @param PHPUnit_Framework_MockObject_MockObject $mockObject
1329
     */
1330
    public function registerMockObject(PHPUnit_Framework_MockObject_MockObject $mockObject)
1331
    {
1332
        $this->mockObjects[] = $mockObject;
1333
    }
1334
1335
    /**
1336
     * This method is a wrapper for the ini_set() function that automatically
1337
     * resets the modified php.ini setting to its original value after the
1338
     * test is run.
1339
     *
1340
     * @param string $varName
1341
     * @param string $newValue
1342
     *
1343
     * @throws Exception
1344
     */
1345
    protected function iniSet($varName, $newValue)
1346
    {
1347
        if (!\is_string($varName)) {
1348
            throw InvalidArgumentHelper::factory(1, 'string');
1349
        }
1350
1351
        $currentValue = \ini_set($varName, $newValue);
1352
1353
        if ($currentValue !== false) {
1354
            $this->iniSettings[$varName] = $currentValue;
1355
        } else {
1356
            throw new Exception(
1357
                \sprintf(
1358
                    'INI setting "%s" could not be set to "%s".',
1359
                    $varName,
1360
                    $newValue
1361
                )
1362
            );
1363
        }
1364
    }
1365
1366
    /**
1367
     * This method is a wrapper for the setlocale() function that automatically
1368
     * resets the locale to its original value after the test is run.
1369
     *
1370
     * @param int    $category
0 ignored issues
show
Bug introduced by
There is no parameter named $category. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1371
     * @param string $locale
0 ignored issues
show
Bug introduced by
There is no parameter named $locale. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1372
     *
1373
     * @throws Exception
1374
     */
1375
    protected function setLocale()
1376
    {
1377
        $args = \func_get_args();
1378
1379
        if (\count($args) < 2) {
1380
            throw new Exception;
1381
        }
1382
1383
        $category = $args[0];
1384
        $locale   = $args[1];
1385
1386
        $categories = [
1387
            LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME
1388
        ];
1389
1390
        if (\defined('LC_MESSAGES')) {
1391
            $categories[] = LC_MESSAGES;
1392
        }
1393
1394
        if (!\in_array($category, $categories)) {
1395
            throw new Exception;
1396
        }
1397
1398
        if (!\is_array($locale) && !\is_string($locale)) {
1399
            throw new Exception;
1400
        }
1401
1402
        $this->locale[$category] = \setlocale($category, 0);
1403
1404
        $result = \call_user_func_array('setlocale', $args);
1405
1406
        if ($result === false) {
1407
            throw new Exception(
1408
                'The locale functionality is not implemented on your platform, ' .
1409
                'the specified locale does not exist or the category name is ' .
1410
                'invalid.'
1411
            );
1412
        }
1413
    }
1414
1415
    /**
1416
     * Returns a builder object to create mock objects using a fluent interface.
1417
     *
1418
     * @param string $className
1419
     *
1420
     * @return PHPUnit_Framework_MockObject_MockBuilder
1421
     */
1422
    public function getMockBuilder($className)
1423
    {
1424
        return new PHPUnit_Framework_MockObject_MockBuilder($this, $className);
1425
    }
1426
1427
    /**
1428
     * Returns a test double for the specified class.
1429
     *
1430
     * @param string $originalClassName
1431
     *
1432
     * @return PHPUnit_Framework_MockObject_MockObject
1433
     *
1434
     * @throws Exception
1435
     */
1436
    protected function createMock($originalClassName)
1437
    {
1438
        return $this->getMockBuilder($originalClassName)
1439
            ->disableOriginalConstructor()
1440
            ->disableOriginalClone()
1441
            ->disableArgumentCloning()
1442
            ->disallowMockingUnknownTypes()
1443
            ->getMock();
1444
    }
1445
1446
    /**
1447
     * Returns a configured test double for the specified class.
1448
     *
1449
     * @param string $originalClassName
1450
     * @param array  $configuration
1451
     *
1452
     * @return PHPUnit_Framework_MockObject_MockObject
1453
     *
1454
     * @throws Exception
1455
     */
1456
    protected function createConfiguredMock($originalClassName, array $configuration)
1457
    {
1458
        $o = $this->createMock($originalClassName);
1459
1460
        foreach ($configuration as $method => $return) {
1461
            $o->method($method)->willReturn($return);
1462
        }
1463
1464
        return $o;
1465
    }
1466
1467
    /**
1468
     * Returns a partial test double for the specified class.
1469
     *
1470
     * @param string $originalClassName
1471
     * @param array  $methods
1472
     *
1473
     * @return PHPUnit_Framework_MockObject_MockObject
1474
     *
1475
     * @throws Exception
1476
     */
1477
    protected function createPartialMock($originalClassName, array $methods)
1478
    {
1479
        return $this->getMockBuilder($originalClassName)
1480
            ->disableOriginalConstructor()
1481
            ->disableOriginalClone()
1482
            ->disableArgumentCloning()
1483
            ->disallowMockingUnknownTypes()
1484
            ->setMethods(empty($methods) ? null : $methods)
1485
            ->getMock();
1486
    }
1487
1488
    /**
1489
     * Returns a test proxy for the specified class.
1490
     *
1491
     * @param string $originalClassName
1492
     * @param array  $constructorArguments
1493
     *
1494
     * @return PHPUnit_Framework_MockObject_MockObject
1495
     *
1496
     * @throws Exception
1497
     */
1498
    protected function createTestProxy($originalClassName, array $constructorArguments = [])
1499
    {
1500
        return $this->getMockBuilder($originalClassName)
1501
            ->setConstructorArgs($constructorArguments)
1502
            ->enableProxyingToOriginalMethods()
1503
            ->getMock();
1504
    }
1505
1506
    /**
1507
     * Mocks the specified class and returns the name of the mocked class.
1508
     *
1509
     * @param string $originalClassName
1510
     * @param array  $methods
1511
     * @param array  $arguments
1512
     * @param string $mockClassName
1513
     * @param bool   $callOriginalConstructor
1514
     * @param bool   $callOriginalClone
1515
     * @param bool   $callAutoload
1516
     * @param bool   $cloneArguments
1517
     *
1518
     * @return string
1519
     *
1520
     * @throws Exception
1521
     */
1522
    protected function getMockClass($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false)
1523
    {
1524
        $mock = $this->getMockObjectGenerator()->getMock(
1525
            $originalClassName,
1526
            $methods,
1527
            $arguments,
1528
            $mockClassName,
1529
            $callOriginalConstructor,
1530
            $callOriginalClone,
1531
            $callAutoload,
1532
            $cloneArguments
1533
        );
1534
1535
        return \get_class($mock);
1536
    }
1537
1538
    /**
1539
     * Returns a mock object for the specified abstract class with all abstract
1540
     * methods of the class mocked. Concrete methods are not mocked by default.
1541
     * To mock concrete methods, use the 7th parameter ($mockedMethods).
1542
     *
1543
     * @param string $originalClassName
1544
     * @param array  $arguments
1545
     * @param string $mockClassName
1546
     * @param bool   $callOriginalConstructor
1547
     * @param bool   $callOriginalClone
1548
     * @param bool   $callAutoload
1549
     * @param array  $mockedMethods
1550
     * @param bool   $cloneArguments
1551
     *
1552
     * @return PHPUnit_Framework_MockObject_MockObject
1553
     *
1554
     * @throws Exception
1555
     */
1556
    protected function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false)
1557
    {
1558
        $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass(
1559
            $originalClassName,
1560
            $arguments,
1561
            $mockClassName,
1562
            $callOriginalConstructor,
1563
            $callOriginalClone,
1564
            $callAutoload,
1565
            $mockedMethods,
1566
            $cloneArguments
1567
        );
1568
1569
        $this->registerMockObject($mockObject);
1570
1571
        return $mockObject;
1572
    }
1573
1574
    /**
1575
     * Returns a mock object based on the given WSDL file.
1576
     *
1577
     * @param string $wsdlFile
1578
     * @param string $originalClassName
1579
     * @param string $mockClassName
1580
     * @param array  $methods
1581
     * @param bool   $callOriginalConstructor
1582
     * @param array  $options                 An array of options passed to SOAPClient::_construct
1583
     *
1584
     * @return PHPUnit_Framework_MockObject_MockObject
1585
     */
1586
    protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = [], $callOriginalConstructor = true, array $options = [])
1587
    {
1588
        if ($originalClassName === '') {
1589
            $originalClassName = \pathinfo(\basename(\parse_url($wsdlFile)['path']), PATHINFO_FILENAME);
1590
        }
1591
1592
        if (!\class_exists($originalClassName)) {
1593
            eval(
1594
                $this->getMockObjectGenerator()->generateClassFromWsdl(
1595
                    $wsdlFile,
1596
                    $originalClassName,
1597
                    $methods,
1598
                    $options
1599
                )
1600
            );
1601
        }
1602
1603
        $mockObject = $this->getMockObjectGenerator()->getMock(
1604
            $originalClassName,
1605
            $methods,
1606
            ['', $options],
1607
            $mockClassName,
1608
            $callOriginalConstructor,
1609
            false,
1610
            false
1611
        );
1612
1613
        $this->registerMockObject($mockObject);
1614
1615
        return $mockObject;
1616
    }
1617
1618
    /**
1619
     * Returns a mock object for the specified trait with all abstract methods
1620
     * of the trait mocked. Concrete methods to mock can be specified with the
1621
     * `$mockedMethods` parameter.
1622
     *
1623
     * @param string $traitName
1624
     * @param array  $arguments
1625
     * @param string $mockClassName
1626
     * @param bool   $callOriginalConstructor
1627
     * @param bool   $callOriginalClone
1628
     * @param bool   $callAutoload
1629
     * @param array  $mockedMethods
1630
     * @param bool   $cloneArguments
1631
     *
1632
     * @return PHPUnit_Framework_MockObject_MockObject
1633
     *
1634
     * @throws Exception
1635
     */
1636
    protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false)
1637
    {
1638
        $mockObject = $this->getMockObjectGenerator()->getMockForTrait(
1639
            $traitName,
1640
            $arguments,
1641
            $mockClassName,
1642
            $callOriginalConstructor,
1643
            $callOriginalClone,
1644
            $callAutoload,
1645
            $mockedMethods,
1646
            $cloneArguments
1647
        );
1648
1649
        $this->registerMockObject($mockObject);
1650
1651
        return $mockObject;
1652
    }
1653
1654
    /**
1655
     * Returns an object for the specified trait.
1656
     *
1657
     * @param string $traitName
1658
     * @param array  $arguments
1659
     * @param string $traitClassName
1660
     * @param bool   $callOriginalConstructor
1661
     * @param bool   $callOriginalClone
1662
     * @param bool   $callAutoload
1663
     *
1664
     * @return object
1665
     *
1666
     * @throws Exception
1667
     */
1668
    protected function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true)
1669
    {
1670
        return $this->getMockObjectGenerator()->getObjectForTrait(
1671
            $traitName,
1672
            $arguments,
1673
            $traitClassName,
1674
            $callOriginalConstructor,
1675
            $callOriginalClone,
1676
            $callAutoload
1677
        );
1678
    }
1679
1680
    /**
1681
     * @param string|null $classOrInterface
1682
     *
1683
     * @return \Prophecy\Prophecy\ObjectProphecy
1684
     *
1685
     * @throws \LogicException
1686
     */
1687
    protected function prophesize($classOrInterface = null)
1688
    {
1689
        return $this->getProphet()->prophesize($classOrInterface);
1690
    }
1691
1692
    /**
1693
     * Adds a value to the assertion counter.
1694
     *
1695
     * @param int $count
1696
     */
1697
    public function addToAssertionCount($count)
1698
    {
1699
        $this->numAssertions += $count;
1700
    }
1701
1702
    /**
1703
     * Returns the number of assertions performed by this test.
1704
     *
1705
     * @return int
1706
     */
1707
    public function getNumAssertions()
1708
    {
1709
        return $this->numAssertions;
1710
    }
1711
1712
    /**
1713
     * Returns a matcher that matches when the method is executed
1714
     * zero or more times.
1715
     *
1716
     * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount
1717
     */
1718
    public static function any()
1719
    {
1720
        return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
1721
    }
1722
1723
    /**
1724
     * Returns a matcher that matches when the method is never executed.
1725
     *
1726
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1727
     */
1728
    public static function never()
1729
    {
1730
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0);
1731
    }
1732
1733
    /**
1734
     * Returns a matcher that matches when the method is executed
1735
     * at least N times.
1736
     *
1737
     * @param int $requiredInvocations
1738
     *
1739
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount
1740
     */
1741
    public static function atLeast($requiredInvocations)
1742
    {
1743
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount(
1744
            $requiredInvocations
1745
        );
1746
    }
1747
1748
    /**
1749
     * Returns a matcher that matches when the method is executed at least once.
1750
     *
1751
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce
1752
     */
1753
    public static function atLeastOnce()
1754
    {
1755
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
1756
    }
1757
1758
    /**
1759
     * Returns a matcher that matches when the method is executed exactly once.
1760
     *
1761
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1762
     */
1763
    public static function once()
1764
    {
1765
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1);
1766
    }
1767
1768
    /**
1769
     * Returns a matcher that matches when the method is executed
1770
     * exactly $count times.
1771
     *
1772
     * @param int $count
1773
     *
1774
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1775
     */
1776
    public static function exactly($count)
1777
    {
1778
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count);
1779
    }
1780
1781
    /**
1782
     * Returns a matcher that matches when the method is executed
1783
     * at most N times.
1784
     *
1785
     * @param int $allowedInvocations
1786
     *
1787
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount
1788
     */
1789
    public static function atMost($allowedInvocations)
1790
    {
1791
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount(
1792
            $allowedInvocations
1793
        );
1794
    }
1795
1796
    /**
1797
     * Returns a matcher that matches when the method is executed
1798
     * at the given index.
1799
     *
1800
     * @param int $index
1801
     *
1802
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
1803
     */
1804
    public static function at($index)
1805
    {
1806
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index);
1807
    }
1808
1809
    /**
1810
     * @param mixed $value
1811
     *
1812
     * @return PHPUnit_Framework_MockObject_Stub_Return
1813
     */
1814
    public static function returnValue($value)
1815
    {
1816
        return new PHPUnit_Framework_MockObject_Stub_Return($value);
1817
    }
1818
1819
    /**
1820
     * @param array $valueMap
1821
     *
1822
     * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap
1823
     */
1824
    public static function returnValueMap(array $valueMap)
1825
    {
1826
        return new PHPUnit_Framework_MockObject_Stub_ReturnValueMap($valueMap);
1827
    }
1828
1829
    /**
1830
     * @param int $argumentIndex
1831
     *
1832
     * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument
1833
     */
1834
    public static function returnArgument($argumentIndex)
1835
    {
1836
        return new PHPUnit_Framework_MockObject_Stub_ReturnArgument(
1837
            $argumentIndex
1838
        );
1839
    }
1840
1841
    /**
1842
     * @param mixed $callback
1843
     *
1844
     * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback
1845
     */
1846
    public static function returnCallback($callback)
1847
    {
1848
        return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback);
1849
    }
1850
1851
    /**
1852
     * Returns the current object.
1853
     *
1854
     * This method is useful when mocking a fluent interface.
1855
     *
1856
     * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf
1857
     */
1858
    public static function returnSelf()
1859
    {
1860
        return new PHPUnit_Framework_MockObject_Stub_ReturnSelf();
1861
    }
1862
1863
    /**
1864
     * @param Throwable $exception
1865
     *
1866
     * @return PHPUnit_Framework_MockObject_Stub_Exception
1867
     */
1868
    public static function throwException(Throwable $exception)
1869
    {
1870
        return new PHPUnit_Framework_MockObject_Stub_Exception($exception);
1871
    }
1872
1873
    /**
1874
     * @param mixed $value , ...
0 ignored issues
show
Bug introduced by
There is no parameter named $value. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1875
     *
1876
     * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls
1877
     */
1878
    public static function onConsecutiveCalls()
1879
    {
1880
        $args = \func_get_args();
1881
1882
        return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args);
1883
    }
1884
1885
    /**
1886
     * @return bool
1887
     */
1888
    public function usesDataProvider()
1889
    {
1890
        return !empty($this->data);
1891
    }
1892
1893
    /**
1894
     * @return string
1895
     */
1896
    public function dataDescription()
1897
    {
1898
        return \is_string($this->dataName) ? $this->dataName : '';
1899
    }
1900
1901
    /**
1902
     * Gets the data set description of a TestCase.
1903
     *
1904
     * @param bool $includeData
1905
     *
1906
     * @return string
1907
     */
1908
    protected function getDataSetAsString($includeData = true)
1909
    {
1910
        $buffer = '';
1911
1912
        if (!empty($this->data)) {
1913
            if (\is_int($this->dataName)) {
1914
                $buffer .= \sprintf(' with data set #%d', $this->dataName);
1915
            } else {
1916
                $buffer .= \sprintf(' with data set "%s"', $this->dataName);
1917
            }
1918
1919
            $exporter = new Exporter;
1920
1921
            if ($includeData) {
1922
                $buffer .= \sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data));
1923
            }
1924
        }
1925
1926
        return $buffer;
1927
    }
1928
1929
    /**
1930
     * Gets the data set of a TestCase.
1931
     *
1932
     * @return array
1933
     */
1934
    protected function getProvidedData()
1935
    {
1936
        return $this->data;
1937
    }
1938
1939
    /**
1940
     * Creates a default TestResult object.
1941
     *
1942
     * @return TestResult
1943
     */
1944
    protected function createResult()
1945
    {
1946
        return new TestResult;
1947
    }
1948
1949
    protected function handleDependencies()
1950
    {
1951
        if (!empty($this->dependencies) && !$this->inIsolation) {
1952
            $className  = \get_class($this);
1953
            $passed     = $this->result->passed();
1954
            $passedKeys = \array_keys($passed);
1955
            $numKeys    = \count($passedKeys);
1956
1957
            for ($i = 0; $i < $numKeys; $i++) {
1958
                $pos = \strpos($passedKeys[$i], ' with data set');
1959
1960
                if ($pos !== false) {
1961
                    $passedKeys[$i] = \substr($passedKeys[$i], 0, $pos);
1962
                }
1963
            }
1964
1965
            $passedKeys = \array_flip(\array_unique($passedKeys));
1966
1967
            foreach ($this->dependencies as $dependency) {
1968
                $clone = false;
1969
1970
                if (\strpos($dependency, 'clone ') === 0) {
1971
                    $clone      = true;
1972
                    $dependency = \substr($dependency, \strlen('clone '));
1973
                } elseif (\strpos($dependency, '!clone ') === 0) {
1974
                    $clone      = false;
1975
                    $dependency = \substr($dependency, \strlen('!clone '));
1976
                }
1977
1978
                if (\strpos($dependency, '::') === false) {
1979
                    $dependency = $className . '::' . $dependency;
1980
                }
1981
1982
                if (!isset($passedKeys[$dependency])) {
1983
                    $this->result->startTest($this);
1984
                    $this->result->addError(
1985
                        $this,
1986
                        new SkippedTestError(
1987
                            \sprintf(
1988
                                'This test depends on "%s" to pass.',
1989
                                $dependency
1990
                            )
1991
                        ),
1992
                        0
1993
                    );
1994
                    $this->result->endTest($this, 0);
1995
1996
                    return false;
1997
                }
1998
1999
                if (isset($passed[$dependency])) {
2000
                    if ($passed[$dependency]['size'] != \PHPUnit\Util\Test::UNKNOWN &&
2001
                        $this->getSize() != \PHPUnit\Util\Test::UNKNOWN &&
2002
                        $passed[$dependency]['size'] > $this->getSize()) {
2003
                        $this->result->addError(
2004
                            $this,
2005
                            new SkippedTestError(
2006
                                'This test depends on a test that is larger than itself.'
2007
                            ),
2008
                            0
2009
                        );
2010
2011
                        return false;
2012
                    }
2013
2014
                    if ($clone) {
2015
                        $deepCopy = new DeepCopy;
2016
                        $deepCopy->skipUncloneable(false);
2017
2018
                        $this->dependencyInput[$dependency] = $deepCopy->copy($passed[$dependency]['result']);
2019
                    } else {
2020
                        $this->dependencyInput[$dependency] = $passed[$dependency]['result'];
2021
                    }
2022
                } else {
2023
                    $this->dependencyInput[$dependency] = null;
2024
                }
2025
            }
2026
        }
2027
2028
        return true;
2029
    }
2030
2031
    /**
2032
     * This method is called before the first test of this test class is run.
2033
     */
2034
    public static function setUpBeforeClass()
2035
    {
2036
    }
2037
2038
    /**
2039
     * Sets up the fixture, for example, open a network connection.
2040
     * This method is called before a test is executed.
2041
     */
2042
    protected function setUp()
2043
    {
2044
    }
2045
2046
    /**
2047
     * Performs assertions shared by all tests of a test case.
2048
     *
2049
     * This method is called before the execution of a test starts
2050
     * and after setUp() is called.
2051
     */
2052
    protected function assertPreConditions()
2053
    {
2054
    }
2055
2056
    /**
2057
     * Performs assertions shared by all tests of a test case.
2058
     *
2059
     * This method is called before the execution of a test ends
2060
     * and before tearDown() is called.
2061
     */
2062
    protected function assertPostConditions()
2063
    {
2064
    }
2065
2066
    /**
2067
     * Tears down the fixture, for example, close a network connection.
2068
     * This method is called after a test is executed.
2069
     */
2070
    protected function tearDown()
2071
    {
2072
    }
2073
2074
    /**
2075
     * This method is called after the last test of this test class is run.
2076
     */
2077
    public static function tearDownAfterClass()
2078
    {
2079
    }
2080
2081
    /**
2082
     * This method is called when a test method did not execute successfully.
2083
     *
2084
     * @param Throwable $t
2085
     *
2086
     * @throws Throwable
2087
     */
2088
    protected function onNotSuccessfulTest(Throwable $t)
2089
    {
2090
        throw $t;
2091
    }
2092
2093
    /**
2094
     * Performs custom preparations on the process isolation template.
2095
     *
2096
     * @param Text_Template $template
2097
     */
2098
    protected function prepareTemplate(Text_Template $template)
0 ignored issues
show
Unused Code introduced by
The parameter $template is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2099
    {
2100
    }
2101
2102
    /**
2103
     * Get the mock object generator, creating it if it doesn't exist.
2104
     *
2105
     * @return PHPUnit_Framework_MockObject_Generator
2106
     */
2107
    private function getMockObjectGenerator()
2108
    {
2109
        if (null === $this->mockObjectGenerator) {
2110
            $this->mockObjectGenerator = new PHPUnit_Framework_MockObject_Generator;
0 ignored issues
show
Documentation Bug introduced by
It seems like new \PHPUnit_Framework_MockObject_Generator() of type object<PHPUnit_Framework_MockObject_Generator> is incompatible with the declared type array of property $mockObjectGenerator.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
2111
        }
2112
2113
        return $this->mockObjectGenerator;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->mockObjectGenerator; of type PHPUnit_Framework_MockObject_Generator|array adds the type array to the return on line 2113 which is incompatible with the return type documented by PHPUnit\Framework\TestCase::getMockObjectGenerator of type PHPUnit_Framework_MockObject_Generator.
Loading history...
2114
    }
2115
2116
    private function startOutputBuffering()
2117
    {
2118
        \ob_start();
2119
2120
        $this->outputBufferingActive = true;
2121
        $this->outputBufferingLevel  = \ob_get_level();
2122
    }
2123
2124
    private function stopOutputBuffering()
2125
    {
2126
        if (\ob_get_level() != $this->outputBufferingLevel) {
2127
            while (\ob_get_level() >= $this->outputBufferingLevel) {
2128
                \ob_end_clean();
2129
            }
2130
2131
            throw new RiskyTestError(
2132
                'Test code or tested code did not (only) close its own output buffers'
2133
            );
2134
        }
2135
2136
        $output = \ob_get_contents();
2137
2138
        if ($this->outputCallback === false) {
2139
            $this->output = $output;
2140
        } else {
2141
            $this->output = \call_user_func_array(
2142
                $this->outputCallback,
2143
                [$output]
2144
            );
2145
        }
2146
2147
        \ob_end_clean();
2148
2149
        $this->outputBufferingActive = false;
2150
        $this->outputBufferingLevel  = \ob_get_level();
2151
    }
2152
2153
    private function snapshotGlobalState()
2154
    {
2155
        if ($this->runTestInSeparateProcess ||
2156
            $this->inIsolation ||
2157
            (!$this->backupGlobals === true && !$this->backupStaticAttributes)) {
2158
            return;
2159
        }
2160
2161
        $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true);
2162
    }
2163
2164
    private function restoreGlobalState()
2165
    {
2166
        if (!$this->snapshot instanceof Snapshot) {
2167
            return;
2168
        }
2169
2170
        if ($this->beStrictAboutChangesToGlobalState) {
2171
            try {
2172
                $this->compareGlobalStateSnapshots(
2173
                    $this->snapshot,
2174
                    $this->createGlobalStateSnapshot($this->backupGlobals === true)
2175
                );
2176
            } catch (RiskyTestError $rte) {
2177
                // Intentionally left empty
2178
            }
2179
        }
2180
2181
        $restorer = new Restorer;
2182
2183
        if ($this->backupGlobals === true) {
2184
            $restorer->restoreGlobalVariables($this->snapshot);
2185
        }
2186
2187
        if ($this->backupStaticAttributes) {
2188
            $restorer->restoreStaticAttributes($this->snapshot);
2189
        }
2190
2191
        $this->snapshot = null;
2192
2193
        if (isset($rte)) {
2194
            throw $rte;
2195
        }
2196
    }
2197
2198
    /**
2199
     * @param bool $backupGlobals
2200
     *
2201
     * @return Snapshot
2202
     */
2203
    private function createGlobalStateSnapshot($backupGlobals)
2204
    {
2205
        $blacklist = new Blacklist;
2206
2207
        foreach ($this->backupGlobalsBlacklist as $globalVariable) {
2208
            $blacklist->addGlobalVariable($globalVariable);
2209
        }
2210
2211
        if (!\defined('PHPUNIT_TESTSUITE')) {
2212
            $blacklist->addClassNamePrefix('PHPUnit');
2213
            $blacklist->addClassNamePrefix('File_Iterator');
2214
            $blacklist->addClassNamePrefix('SebastianBergmann\CodeCoverage');
2215
            $blacklist->addClassNamePrefix('PHP_Invoker');
2216
            $blacklist->addClassNamePrefix('PHP_Timer');
2217
            $blacklist->addClassNamePrefix('PHP_Token');
2218
            $blacklist->addClassNamePrefix('Symfony');
2219
            $blacklist->addClassNamePrefix('Text_Template');
2220
            $blacklist->addClassNamePrefix('Doctrine\Instantiator');
2221
            $blacklist->addClassNamePrefix('Prophecy');
2222
2223
            foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) {
2224
                foreach ($attributes as $attribute) {
2225
                    $blacklist->addStaticAttribute($class, $attribute);
2226
                }
2227
            }
2228
        }
2229
2230
        return new Snapshot(
2231
            $blacklist,
2232
            $backupGlobals,
2233
            (bool) $this->backupStaticAttributes,
2234
            false,
2235
            false,
2236
            false,
2237
            false,
2238
            false,
2239
            false,
2240
            false
2241
        );
2242
    }
2243
2244
    /**
2245
     * @param Snapshot $before
2246
     * @param Snapshot $after
2247
     *
2248
     * @throws RiskyTestError
2249
     */
2250
    private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after)
2251
    {
2252
        $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true;
2253
2254
        if ($backupGlobals) {
2255
            $this->compareGlobalStateSnapshotPart(
2256
                $before->globalVariables(),
2257
                $after->globalVariables(),
2258
                "--- Global variables before the test\n+++ Global variables after the test\n"
2259
            );
2260
2261
            $this->compareGlobalStateSnapshotPart(
2262
                $before->superGlobalVariables(),
2263
                $after->superGlobalVariables(),
2264
                "--- Super-global variables before the test\n+++ Super-global variables after the test\n"
2265
            );
2266
        }
2267
2268
        if ($this->backupStaticAttributes) {
2269
            $this->compareGlobalStateSnapshotPart(
2270
                $before->staticAttributes(),
2271
                $after->staticAttributes(),
2272
                "--- Static attributes before the test\n+++ Static attributes after the test\n"
2273
            );
2274
        }
2275
    }
2276
2277
    /**
2278
     * @param array  $before
2279
     * @param array  $after
2280
     * @param string $header
2281
     *
2282
     * @throws RiskyTestError
2283
     */
2284
    private function compareGlobalStateSnapshotPart(array $before, array $after, $header)
2285
    {
2286
        if ($before != $after) {
2287
            $differ   = new Differ($header);
2288
            $exporter = new Exporter;
2289
2290
            $diff = $differ->diff(
2291
                $exporter->export($before),
2292
                $exporter->export($after)
2293
            );
2294
2295
            throw new RiskyTestError(
2296
                $diff
2297
            );
2298
        }
2299
    }
2300
2301
    /**
2302
     * @return Prophecy\Prophet
2303
     */
2304
    private function getProphet()
2305
    {
2306
        if ($this->prophet === null) {
2307
            $this->prophet = new Prophet;
2308
        }
2309
2310
        return $this->prophet;
2311
    }
2312
2313
    /**
2314
     * @param PHPUnit_Framework_MockObject_MockObject $mock
2315
     *
2316
     * @return bool
2317
     */
2318
    private function shouldInvocationMockerBeReset(PHPUnit_Framework_MockObject_MockObject $mock)
2319
    {
2320
        $enumerator = new Enumerator;
2321
2322
        foreach ($enumerator->enumerate($this->dependencyInput) as $object) {
2323
            if ($mock === $object) {
2324
                return false;
2325
            }
2326
        }
2327
2328
        if (!\is_array($this->testResult) && !\is_object($this->testResult)) {
2329
            return true;
2330
        }
2331
2332
        foreach ($enumerator->enumerate($this->testResult) as $object) {
2333
            if ($mock === $object) {
2334
                return false;
2335
            }
2336
        }
2337
2338
        return true;
2339
    }
2340
2341
    /**
2342
     * @param array $testArguments
2343
     * @param array $originalTestArguments
0 ignored issues
show
Documentation introduced by
There is no parameter named $originalTestArguments. Did you maybe mean $testArguments?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
2344
     */
2345
    private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = [])
2346
    {
2347
        if ($this->registerMockObjectsFromTestArgumentsRecursively) {
2348
            $enumerator = new Enumerator;
2349
2350
            foreach ($enumerator->enumerate($testArguments) as $object) {
2351
                if ($object instanceof PHPUnit_Framework_MockObject_MockObject) {
2352
                    $this->registerMockObject($object);
2353
                }
2354
            }
2355
        } else {
2356
            foreach ($testArguments as $testArgument) {
2357
                if ($testArgument instanceof PHPUnit_Framework_MockObject_MockObject) {
2358
                    if ($this->isCloneable($testArgument)) {
2359
                        $testArgument = clone $testArgument;
2360
                    }
2361
2362
                    $this->registerMockObject($testArgument);
2363
                } elseif (\is_array($testArgument) && !\in_array($testArgument, $visited, true)) {
2364
                    $visited[] = $testArgument;
2365
2366
                    $this->registerMockObjectsFromTestArguments(
2367
                        $testArgument,
2368
                        $visited
2369
                    );
2370
                }
2371
            }
2372
        }
2373
    }
2374
2375
    private function setDoesNotPerformAssertionsFromAnnotation()
2376
    {
2377
        $annotations = $this->getAnnotations();
2378
2379
        if (isset($annotations['method']['doesNotPerformAssertions'])) {
2380
            $this->doesNotPerformAssertions = true;
2381
        }
2382
    }
2383
2384
    /**
2385
     * @param PHPUnit_Framework_MockObject_MockObject $testArgument
2386
     *
2387
     * @return bool
2388
     */
2389
    private function isCloneable(PHPUnit_Framework_MockObject_MockObject $testArgument)
2390
    {
2391
        $reflector = new ReflectionObject($testArgument);
2392
2393
        if (!$reflector->isCloneable()) {
2394
            return false;
2395
        }
2396
2397
        if ($reflector->hasMethod('__clone') &&
2398
            $reflector->getMethod('__clone')->isPublic()) {
2399
            return true;
2400
        }
2401
2402
        return false;
2403
    }
2404
}
2405