├── CHANGES.md ├── LICENSE ├── README.md ├── composer.json └── src └── ProphecyTrait.php /CHANGES.md: -------------------------------------------------------------------------------- 1 | # 2.4.0 2 | * Add support for PHPUnit 12 3 | 4 | # 2.3.0 5 | 6 | * Add more precise type for the `prophesize` method 7 | 8 | # 2.2.0 9 | 10 | * Add support for PHPUnit 11 11 | 12 | # 2.1.0 / 2023-12-08 13 | 14 | Add support for PHPUnit 10.1+ (10.0 is not supported) 15 | Bump requirement to Prophecy 1.18+ 16 | 17 | # 2.0.2 / 2023-04-18 18 | 19 | Add the `@not-deprecated` annotation to avoid phpstan reporting `prophesize` as deprecated due to the TestCase deprecation. 20 | 21 | # 2.0.1 / 2020-07-09 22 | 23 | Add support for PHP 8 24 | 25 | # 2.0.0 / 2020-04-07 26 | 27 | Rewrite of the library for PHPUnit 9.1+, with a new API based on a trait rather than a base class. 28 | 29 | 1.1.0 / 2015-02-09 30 | ================== 31 | 32 | * Remove the requirement to call the parent ``setUp`` method 33 | * Add the assertion count for predictions to be compatible with PHPUnit strict mode 34 | 35 | 1.0.1 / 2014-03-04 36 | ================== 37 | 38 | * Marked the ``ProphecyTestCase`` as abstract to avoid PhpUnit to try running it 39 | 40 | 1.0.0 / 2013-07-04 41 | ================== 42 | 43 | * Initial release 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Christophe Coevoet 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prophecy 2 | 3 | [![Build Status](https://github.com/phpspec/prophecy-phpunit/actions/workflows/ci.yml/badge.svg)](https://github.com/phpspec/prophecy-phpunit/actions/workflows/ci.yml) 4 | 5 | Prophecy PhpUnit integrates the [Prophecy](https://github.com/phpspec/prophecy) mocking 6 | library with [PHPUnit](https://phpunit.de) to provide an easier mocking in your testsuite. 7 | 8 | ## Installation 9 | 10 | ### Prerequisites 11 | 12 | Prophecy PhpUnit requires PHP 7.3 or greater. 13 | Prophecy PhpUnit requires PHPUnit 9.1 or greater. Older versions of PHPUnit are providing the Prophecy integration themselves. 14 | 15 | ### Setup through composer 16 | 17 | ```bash 18 | composer require --dev phpspec/prophecy-phpunit 19 | ``` 20 | 21 | You can read more about Composer on its [official webpage](https://getcomposer.org). 22 | 23 | ## How to use it 24 | 25 | The trait ``ProphecyTrait`` provides a method ``prophesize($classOrInterface = null)`` to use Prophecy. 26 | For the usage of the Prophecy doubles, please refer to the [Prophecy documentation](https://github.com/phpspec/prophecy). 27 | 28 | Below is a usage example: 29 | 30 | ```php 31 | prophesize(Hasher::class); 47 | $user = new User($hasher->reveal()); 48 | 49 | $hasher->generateHash($user, 'qwerty')->willReturn('hashed_pass'); 50 | 51 | $user->setPassword('qwerty'); 52 | 53 | $this->assertEquals('hashed_pass', $user->getPassword()); 54 | } 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpspec/prophecy-phpunit", 3 | "description": "Integrating the Prophecy mocking library in PHPUnit test cases", 4 | "keywords": ["Phpunit", "Prophecy"], 5 | "homepage": "http://phpspec.net", 6 | "type": "library", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Christophe Coevoet", 11 | "email": "stof@notk.org" 12 | } 13 | ], 14 | "require": { 15 | "php": "^7.3 || ^8", 16 | "phpspec/prophecy": "^1.18", 17 | "phpunit/phpunit":"^9.1 || ^10.1 || ^11.0 || ^12.0" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Prophecy\\PhpUnit\\": "src" 22 | } 23 | }, 24 | "autoload-dev": { 25 | "psr-4": { 26 | "Prophecy\\PhpUnit\\Tests\\Fixtures\\": "fixtures", 27 | "Prophecy\\PhpUnit\\Tests\\PhpstanFixtures\\": "phpstan-fixtures", 28 | "Prophecy\\PhpUnit\\Tests\\": "tests" 29 | } 30 | }, 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "2.x-dev" 34 | } 35 | }, 36 | "require-dev": { 37 | "phpstan/phpstan": "^1.10" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ProphecyTrait.php: -------------------------------------------------------------------------------- 1 | |null $classOrInterface 41 | * @phpstan-return ($classOrInterface is null ? ObjectProphecy : ObjectProphecy) 42 | * 43 | * @not-deprecated 44 | */ 45 | protected function prophesize(?string $classOrInterface = null): ObjectProphecy 46 | { 47 | static $isPhpUnit9; 48 | $isPhpUnit9 = $isPhpUnit9 ?? method_exists($this, 'recordDoubledType'); 49 | 50 | if (! $isPhpUnit9) { 51 | // PHPUnit 10.1 52 | $this->registerFailureType(PredictionException::class); 53 | } elseif (\is_string($classOrInterface)) { 54 | // PHPUnit 9 55 | \assert($this instanceof TestCase); 56 | $this->recordDoubledType($classOrInterface); 57 | } 58 | 59 | return $this->getProphet()->prophesize($classOrInterface); 60 | } 61 | 62 | /** 63 | * @postCondition 64 | */ 65 | #[PostCondition] 66 | protected function verifyProphecyDoubles(): void 67 | { 68 | if ($this->prophet === null) { 69 | return; 70 | } 71 | 72 | try { 73 | $this->prophet->checkPredictions(); 74 | } catch (PredictionException $e) { 75 | throw new AssertionFailedError($e->getMessage()); 76 | } finally { 77 | $this->countProphecyAssertions(); 78 | } 79 | } 80 | 81 | /** 82 | * @after 83 | */ 84 | #[After] 85 | protected function tearDownProphecy(): void 86 | { 87 | if (null !== $this->prophet && !$this->prophecyAssertionsCounted) { 88 | // Some Prophecy assertions may have been done in tests themselves even when a failure happened before checking mock objects. 89 | $this->countProphecyAssertions(); 90 | } 91 | 92 | $this->prophet = null; 93 | } 94 | 95 | /** 96 | * @internal 97 | */ 98 | private function countProphecyAssertions(): void 99 | { 100 | \assert($this instanceof TestCase); 101 | \assert($this->prophet !== null); 102 | $this->prophecyAssertionsCounted = true; 103 | 104 | foreach ($this->prophet->getProphecies() as $objectProphecy) { 105 | foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { 106 | foreach ($methodProphecies as $methodProphecy) { 107 | \assert($methodProphecy instanceof MethodProphecy); 108 | 109 | $this->addToAssertionCount(\count($methodProphecy->getCheckedPredictions())); 110 | } 111 | } 112 | } 113 | } 114 | 115 | /** 116 | * @internal 117 | */ 118 | private function getProphet(): Prophet 119 | { 120 | if ($this->prophet === null) { 121 | $this->prophet = new Prophet; 122 | } 123 | 124 | return $this->prophet; 125 | } 126 | } 127 | --------------------------------------------------------------------------------