Aggiornato Composer

This commit is contained in:
Paolo A
2024-05-17 12:24:19 +00:00
parent 4ac62108b5
commit ec201d75b2
2238 changed files with 38684 additions and 59785 deletions

View File

@@ -2,10 +2,10 @@
namespace PHPSTORM_META;
override(\Mockery::mock(0), type(0));
override(\Mockery::spy(0), type(0));
override(\Mockery::namedMock(0), type(0));
override(\Mockery::instanceMock(0), type(0));
override(\mock(0), type(0));
override(\spy(0), type(0));
override(\namedMock(0), type(0));
override(\Mockery::mock(0), map(["" => "@"]));
override(\Mockery::spy(0), map(["" => "@"]));
override(\Mockery::namedMock(0), map(["" => "@"]));
override(\Mockery::instanceMock(0), map(["" => "@"]));
override(\mock(0), map(["" => "@"]));
override(\spy(0), map(["" => "@"]));
override(\namedMock(0), map(["" => "@"]));

View File

@@ -1,200 +1,419 @@
# Change Log
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.6.12] - 2024-05-15
### Changed
- [1420: Update `psalm-baseline.xml` ](https://github.com/mockery/mockery/pull/1420)
- [1419: Update e2e-test.sh](https://github.com/mockery/mockery/pull/1419)
- [1413: Upgrade `phar` tools and `phive.xml` configuration](https://github.com/mockery/mockery/pull/1413)
### Fixed
- [1415: Fix mocking anonymous classes](https://github.com/mockery/mockery/pull/1415)
- [1411: Mocking final classes reports unresolvable type by PHPStan](https://github.com/mockery/mockery/issues/1411)
- [1410: Fix PHP Doc Comments](https://github.com/mockery/mockery/pull/1410)
### Security
- [1417: Bump `Jinja2` from `3.1.3` to `3.1.4` fix CVE-2024-34064](https://github.com/mockery/mockery/pull/1417)
- [1412: Bump `idna` from `3.6` to `3.7` fix CVE-2024-3651](https://github.com/mockery/mockery/pull/1412)
## [1.6.11] - 2024-03-21
### Fixed
- [1407: Fix constants map generics doc comments](https://github.com/mockery/mockery/pull/1407)
- [1406: Fix reserved words used to name a class, interface or trait](https://github.com/mockery/mockery/pull/1406)
- [1403: Fix regression - partial construction with trait methods](https://github.com/mockery/mockery/pull/1403)
- [1401: Improve `Mockery::mock()` parameter type compatibility with array typehints](https://github.com/mockery/mockery/pull/1401)
## [1.6.10] - 2024-03-19
### Added
- [1398: [PHP 8.4] Fixes for implicit nullability deprecation](https://github.com/mockery/mockery/pull/1398)
### Fixed
- [1397: Fix mock method $args parameter type](https://github.com/mockery/mockery/pull/1397)
- [1396: Fix `1.6.8` release](https://github.com/mockery/mockery/pull/1396)
## [1.6.9] - 2024-03-12
- [1394: Revert v1.6.8 release](https://github.com/mockery/mockery/pull/1394)
## [1.6.8] - 2024-03-12
- [1393: Changelog v1.6.8](https://github.com/mockery/mockery/pull/1393)
- [1392: Refactor remaining codebase](https://github.com/mockery/mockery/pull/1392)
- [1391: Update actions to use Node 20](https://github.com/mockery/mockery/pull/1391)
- [1390: Update `ReadTheDocs` dependencies](https://github.com/mockery/mockery/pull/1390)
- [1389: Refactor `library/Mockery/Matcher/*`](https://github.com/mockery/mockery/pull/1389)
- [1388: Refactor `library/Mockery/Loader/*`](https://github.com/mockery/mockery/pull/1388)
- [1387: Refactor `library/Mockery/CountValidator/*`](https://github.com/mockery/mockery/pull/1387)
- [1386: Add PHPUnit 10+ attributes](https://github.com/mockery/mockery/pull/1386)
- [1385: Update composer dependencies and clean up](https://github.com/mockery/mockery/pull/1385)
- [1384: Update `psalm-baseline.xml`](https://github.com/mockery/mockery/pull/1384)
- [1383: Refactor `library/helpers.php`](https://github.com/mockery/mockery/pull/1383)
- [1382: Refactor `library/Mockery/VerificationExpectation.php`](https://github.com/mockery/mockery/pull/1382)
- [1381: Refactor `library/Mockery/VerificationDirector.php`](https://github.com/mockery/mockery/pull/1381)
- [1380: Refactor `library/Mockery/QuickDefinitionsConfiguration.php`](https://github.com/mockery/mockery/pull/1380)
- [1379: Refactor `library/Mockery/Undefined.php`](https://github.com/mockery/mockery/pull/1379)
- [1378: Refactor `library/Mockery/Reflector.php`](https://github.com/mockery/mockery/pull/1378)
- [1377: Refactor `library/Mockery/ReceivedMethodCalls.php`](https://github.com/mockery/mockery/pull/1377)
- [1376: Refactor `library/Mockery.php`](https://github.com/mockery/mockery/pull/1376)
- [1375: Refactor `library/Mockery/MockInterface.php`](https://github.com/mockery/mockery/pull/1375)
- [1374: Refactor `library/Mockery/MethodCall.php`](https://github.com/mockery/mockery/pull/1374)
- [1373: Refactor `library/Mockery/LegacyMockInterface.php`](https://github.com/mockery/mockery/pull/1373)
- [1372: Refactor `library/Mockery/Instantiator.php`](https://github.com/mockery/mockery/pull/1372)
- [1371: Refactor `library/Mockery/HigherOrderMessage.php`](https://github.com/mockery/mockery/pull/1371)
- [1370: Refactor `library/Mockery/ExpectsHigherOrderMessage.php`](https://github.com/mockery/mockery/pull/1370)
- [1369: Refactor `library/Mockery/ExpectationInterface.php`](https://github.com/mockery/mockery/pull/1369)
- [1368: Refactor `library/Mockery/ExpectationDirector.php`](https://github.com/mockery/mockery/pull/1368)
- [1367: Refactor `library/Mockery/Expectation.php`](https://github.com/mockery/mockery/pull/1367)
- [1366: Refactor `library/Mockery/Exception.php`](https://github.com/mockery/mockery/pull/1366)
- [1365: Refactor `library/Mockery/Container.php`](https://github.com/mockery/mockery/pull/1365)
- [1364: Refactor `library/Mockery/Configuration.php`](https://github.com/mockery/mockery/pull/1364)
- [1363: Refactor `library/Mockery/CompositeExpectation.php`](https://github.com/mockery/mockery/pull/1363)
- [1362: Refactor `library/Mockery/ClosureWrapper.php`](https://github.com/mockery/mockery/pull/1362)
- [1361: Refactor `library/Mockery.php`](https://github.com/mockery/mockery/pull/1361)
- [1360: Refactor Container](https://github.com/mockery/mockery/pull/1360)
- [1355: Fix the namespace in the SubsetTest class](https://github.com/mockery/mockery/pull/1355)
- [1354: Add array-like objects support to hasKey/hasValue matchers](https://github.com/mockery/mockery/pull/1354)
## [1.6.7] - 2023-12-09
### Added
- [#1338: Support PHPUnit constraints as matchers](https://github.com/mockery/mockery/pull/1338)
- [#1336: Add factory methods for `IsEqual` and `IsSame` matchers](https://github.com/mockery/mockery/pull/1336)
### Fixed
- [#1346: Fix test namespaces](https://github.com/mockery/mockery/pull/1346)
- [#1343: Update documentation default theme and build version](https://github.com/mockery/mockery/pull/1343)
- [#1329: Prevent `shouldNotReceive` from getting overridden by invocation count methods](https://github.com/mockery/mockery/pull/1329)
### Changed
- [#1351: Update psalm-baseline.xml](https://github.com/mockery/mockery/pull/1351)
- [#1350: Changelog v1.6.7](https://github.com/mockery/mockery/pull/1350)
- [#1349: Cleanup](https://github.com/mockery/mockery/pull/1349)
- [#1348: Update makefile](https://github.com/mockery/mockery/pull/1348)
- [#1347: Bump phars dependencies](https://github.com/mockery/mockery/pull/1347)
- [#1344: Disabled travis-ci and sensiolabs webhooks](https://github.com/mockery/mockery/issues/1344)
- [#1342: Add `.readthedocs.yml` configuration](https://github.com/mockery/mockery/pull/1342)
- [#1340: docs: Remove misplaced semicolumn from code snippet](https://github.com/mockery/mockery/pull/1340)
## 1.6.6 (2023-08-08)
- [#1327: Changelog v1.6.6](https://github.com/mockery/mockery/pull/1327)
- [#1325: Keep the file that caused an error for inspection](https://github.com/mockery/mockery/pull/1325)
- [#1324: Fix Regression - Replace `+` Array Union Operator with `array_merge`](https://github.com/mockery/mockery/pull/1324)
## 1.6.5 (2023-08-05)
- [#1322: Changelog v1.6.5](https://github.com/mockery/mockery/pull/1322)
- [#1321: Autoload Test Fixtures Based on PHP Runtime Version](https://github.com/mockery/mockery/pull/1321)
- [#1320: Clean up mocks on destruct](https://github.com/mockery/mockery/pull/1320)
- [#1318: Fix misspelling in docs](https://github.com/mockery/mockery/pull/1318)
- [#1316: Fix compatibility issues with PHP 7.3](https://github.com/mockery/mockery/pull/1316)
- [#1315: Fix PHP 7.3 issues](https://github.com/mockery/mockery/issues/1315)
- [#1314: Add Security Policy](https://github.com/mockery/mockery/pull/1314)
- [#1313: Type declaration for `iterable|object`.](https://github.com/mockery/mockery/pull/1313)
- [#1312: Mock disjunctive normal form types](https://github.com/mockery/mockery/pull/1312)
- [#1299: Test PHP `8.3` language features](https://github.com/mockery/mockery/pull/1299)
## 1.6.4 (2023-07-19)
- [#1308: Changelog v1.6.4](https://github.com/mockery/mockery/pull/1308)
- [#1307: Revert `src` to `library` for `1.6.x`](https://github.com/mockery/mockery/pull/1307)
## 1.6.3 (2023-07-18)
- [#1304: Remove `extra.branch-alias` and update composer information](https://github.com/mockery/mockery/pull/1304)
- [#1303: Update `.gitattributes`](https://github.com/mockery/mockery/pull/1303)
- [#1302: Changelog v1.6.3](https://github.com/mockery/mockery/pull/1302)
- [#1301: Fix mocking classes with `new` initializers in method and attribute params on PHP 8.1](https://github.com/mockery/mockery/pull/1301)
- [#1298: Update default repository branch to latest release branch](https://github.com/mockery/mockery/issues/1298)
- [#1297: Update `Makefile` for contributors](https://github.com/mockery/mockery/pull/1297)
- [#1294: Correct return types of Mock for phpstan](https://github.com/mockery/mockery/pull/1294)
- [#1290: Rename directory `library` to `src`](https://github.com/mockery/mockery/pull/1290)
- [#1288: Update codecov workflow](https://github.com/mockery/mockery/pull/1288)
- [#1287: Update psalm configuration and workflow](https://github.com/mockery/mockery/pull/1287)
- [#1286: Update phpunit workflow](https://github.com/mockery/mockery/pull/1286)
- [#1285: Enforce the minimum required PHP version](https://github.com/mockery/mockery/pull/1285)
- [#1283: Update license and copyright information](https://github.com/mockery/mockery/pull/1283)
- [#1282: Create `COPYRIGHT.md` file](https://github.com/mockery/mockery/pull/1282)
- [#1279: Bump `vimeo/psalm` from `5.9.0` to `5.12.0`](https://github.com/mockery/mockery/pull/1279)
## 1.6.2 (2023-06-07)
- [#1276: Add `IsEqual` Argument Matcher](https://github.com/mockery/mockery/pull/1276)
- [#1275: Add `IsSame` Argument Matcher](https://github.com/mockery/mockery/pull/1275)
- [#1274: Update composer branch alias](https://github.com/mockery/mockery/pull/1274)
- [#1271: Support PHP 8.2 `true` Literal Type](https://github.com/mockery/mockery/pull/1271)
- [#1270: Support PHP 8.0 `false` Literal Type](https://github.com/mockery/mockery/pull/1270)
## 1.6.1 (2023-06-05)
- [#1267 Drops support for PHP <7.4](https://github.com/mockery/mockery/pull/1267)
- [#1192 Updated changelog for version 1.5.1 to include changes from #1180](https://github.com/mockery/mockery/pull/1192)
- [#1196 Update example in README.md](https://github.com/mockery/mockery/pull/1196)
- [#1199 Fix function parameter default enum value](https://github.com/mockery/mockery/pull/1199)
- [#1205 Deal with null type in PHP8.2](https://github.com/mockery/mockery/pull/1205)
- [#1208 Import MockeryTestCase fully qualified class name](https://github.com/mockery/mockery/pull/1208)
- [#1210 Add support for target class attributes](https://github.com/mockery/mockery/pull/1210)
- [#1212 docs: Add missing comma](https://github.com/mockery/mockery/pull/1212)
- [#1216 Fixes code generation for intersection types](https://github.com/mockery/mockery/pull/1216)
- [#1217 Add MockeryExceptionInterface](https://github.com/mockery/mockery/pull/1217)
- [#1218 tidy: avoids require](https://github.com/mockery/mockery/pull/1218)
- [#1222 Add .editorconfig](https://github.com/mockery/mockery/pull/1222)
- [#1225 Switch to PSR-4 autoload](https://github.com/mockery/mockery/pull/1225)
- [#1226 Refactoring risky tests](https://github.com/mockery/mockery/pull/1226)
- [#1230 Add vimeo/psalm and psalm/plugin-phpunit](https://github.com/mockery/mockery/pull/1230)
- [#1232 Split PHPUnit TestSuites for PHP 8.2](https://github.com/mockery/mockery/pull/1232)
- [#1233 Bump actions/checkout to v3](https://github.com/mockery/mockery/pull/1233)
- [#1234 Bump nick-invision/retry to v2](https://github.com/mockery/mockery/pull/1234)
- [#1235 Setup Codecov for code coverage](https://github.com/mockery/mockery/pull/1235)
- [#1236 Add Psalm CI Check](https://github.com/mockery/mockery/pull/1236)
- [#1237 Unignore composer.lock file](https://github.com/mockery/mockery/pull/1237)
- [#1239 Prevent CI run duplication](https://github.com/mockery/mockery/pull/1239)
- [#1241 Add PHPUnit workflow for PHP 8.3](https://github.com/mockery/mockery/pull/1241)
- [#1244 Improve ClassAttributesPass for Dynamic Properties](https://github.com/mockery/mockery/pull/1244)
- [#1245 Deprecate hamcrest/hamcrest-php package](https://github.com/mockery/mockery/pull/1245)
- [#1246 Add BUG_REPORT.yml Issue template](https://github.com/mockery/mockery/pull/1246)
- [#1250 Deprecate PHP <=8.0](https://github.com/mockery/mockery/issues/1250)
- [#1253 Prevent array to string conversion when serialising a Subset matcher](https://github.com/mockery/mockery/issues/1253)
## 1.6.0 (2023-06-05) [DELETED]
This tag was deleted due to a mistake with the composer.json PHP version
constraint, see [#1266](https://github.com/mockery/mockery/issues/1266)
## 1.3.6 (2022-09-07)
- PHP 8.2 | Fix "Use of "parent" in callables is deprecated" notice #1169
## 1.5.1 (2022-09-07)
- [PHP 8.2] Various tests: explicitly declare properties #1170
- [PHP 8.2] Fix "Use of "parent" in callables is deprecated" notice #1169
- [PHP 8.1] Support intersection types #1164
- Handle final `__toString` methods #1162
- Only count assertions on expectations which can fail a test #1180
## 1.5.0 (2022-01-20)
* Override default call count expectations via expects() #1146
* Mock methods with static return types #1157
* Mock methods with mixed return type #1156
* Mock classes with new in initializers on PHP 8.1 #1160
* Removes redundant PHPUnitConstraint #1158
- Override default call count expectations via expects() #1146
- Mock methods with static return types #1157
- Mock methods with mixed return type #1156
- Mock classes with new in initializers on PHP 8.1 #1160
- Removes redundant PHPUnitConstraint #1158
## 1.4.4 (2021-09-13)
* Fixes auto-generated return values #1144
* Adds support for tentative types #1130
* Fixes for PHP 8.1 Support (#1130 and #1140)
* Add method that allows defining a set of arguments the mock should yield #1133
* Added option to configure default matchers for objects `\Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass)` #1120
- Fixes auto-generated return values #1144
- Adds support for tentative types #1130
- Fixes for PHP 8.1 Support (#1130 and #1140)
- Add method that allows defining a set of arguments the mock should yield #1133
- Added option to configure default matchers for objects `\Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass)` #1120
## 1.3.5 (2021-09-13)
- Fix auto-generated return values with union types #1143
- Adds support for tentative types #1130
- Fixes for PHP 8.1 Support (#1130 and #1140)
- Add method that allows defining a set of arguments the mock should yield #1133
- Added option to configure default matchers for objects `\Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass)` #1120
## 1.4.3 (2021-02-24)
* Fixes calls to fetchMock before initialisation #1113
* Allow shouldIgnoreMissing() to behave in a recursive fashion #1097
* Custom object formatters #766 (Needs Docs)
* Fix crash on a union type including null #1106
- Fixes calls to fetchMock before initialisation #1113
- Allow shouldIgnoreMissing() to behave in a recursive fashion #1097
- Custom object formatters #766 (Needs Docs)
- Fix crash on a union type including null #1106
## 1.3.4 (2021-02-24)
* Fixes calls to fetchMock before initialisation #1113
* Fix crash on a union type including null #1106
- Fixes calls to fetchMock before initialisation #1113
- Fix crash on a union type including null #1106
## 1.4.2 (2020-08-11)
* Fix array to string conversion in ConstantsPass (#1086)
* Fixed nullable PHP 8.0 union types (#1088, #1089)
* Fixed support for PHP 8.0 parent type (#1088, #1089)
* Fixed PHP 8.0 mixed type support (#1088, #1089)
* Fixed PHP 8.0 union return types (#1088, #1089)
- Fix array to string conversion in ConstantsPass (#1086)
- Fixed nullable PHP 8.0 union types (#1088, #1089)
- Fixed support for PHP 8.0 parent type (#1088, #1089)
- Fixed PHP 8.0 mixed type support (#1088, #1089)
- Fixed PHP 8.0 union return types (#1088, #1089)
## 1.4.1 (2020-07-09)
* Allow quick definitions to use 'at least once' expectation
- Allow quick definitions to use 'at least once' expectation
`\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce(true)` (#1056)
* Added provisional support for PHP 8.0 (#1068, #1072,#1079)
* Fix mocking methods with iterable return type without specifying a return value (#1075)
- Added provisional support for PHP 8.0 (#1068, #1072,#1079)
- Fix mocking methods with iterable return type without specifying a return value (#1075)
## 1.3.3 (2020-08-11)
* Fix array to string conversion in ConstantsPass (#1086)
* Fixed nullable PHP 8.0 union types (#1088)
* Fixed support for PHP 8.0 parent type (#1088)
* Fixed PHP 8.0 mixed type support (#1088)
* Fixed PHP 8.0 union return types (#1088)
- Fix array to string conversion in ConstantsPass (#1086)
- Fixed nullable PHP 8.0 union types (#1088)
- Fixed support for PHP 8.0 parent type (#1088)
- Fixed PHP 8.0 mixed type support (#1088)
- Fixed PHP 8.0 union return types (#1088)
## 1.3.2 (2020-07-09)
* Fix mocking with anonymous classes (#1039)
* Fix andAnyOthers() to properly match earlier expectations (#1051)
* Added provisional support for PHP 8.0 (#1068, #1072,#1079)
* Fix mocking methods with iterable return type without specifying a return value (#1075)
- Fix mocking with anonymous classes (#1039)
- Fix andAnyOthers() to properly match earlier expectations (#1051)
- Added provisional support for PHP 8.0 (#1068, #1072,#1079)
- Fix mocking methods with iterable return type without specifying a return value (#1075)
## 1.4.0 (2020-05-19)
* Fix mocking with anonymous classes (#1039)
* Fix andAnyOthers() to properly match earlier expectations (#1051)
* Drops support for PHP < 7.3 and PHPUnit < 8 (#1059)
- Fix mocking with anonymous classes (#1039)
- Fix andAnyOthers() to properly match earlier expectations (#1051)
- Drops support for PHP < 7.3 and PHPUnit < 8 (#1059)
## 1.3.1 (2019-12-26)
* Revert improved exception debugging due to BC breaks (#1032)
- Revert improved exception debugging due to BC breaks (#1032)
## 1.3.0 (2019-11-24)
* Added capture `Mockery::capture` convenience matcher (#1020)
* Added `andReturnArg` to echo back an argument passed to a an expectation (#992)
* Improved exception debugging (#1000)
* Fixed `andSet` to not reuse properties between mock objects (#1012)
- Added capture `Mockery::capture` convenience matcher (#1020)
- Added `andReturnArg` to echo back an argument passed to a an expectation (#992)
- Improved exception debugging (#1000)
- Fixed `andSet` to not reuse properties between mock objects (#1012)
## 1.2.4 (2019-09-30)
* Fix a bug introduced with previous release, for empty method definition lists (#1009)
- Fix a bug introduced with previous release, for empty method definition lists (#1009)
## 1.2.3 (2019-08-07)
* Allow mocking classes that have allows and expects methods (#868)
* Allow passing thru __call method in all mock types (experimental) (#969)
* Add support for `!` to blacklist methods (#959)
* Added `withSomeOfArgs` to partial match a list of args (#967)
* Fix chained demeter calls with type hint (#956)
- Allow mocking classes that have allows and expects methods (#868)
- Allow passing thru __call method in all mock types (experimental) (#969)
- Add support for `!` to blacklist methods (#959)
- Added `withSomeOfArgs` to partial match a list of args (#967)
- Fix chained demeter calls with type hint (#956)
## 1.2.2 (2019-02-13)
* Fix a BC breaking change for PHP 5.6/PHPUnit 5.7.27 (#947)
- Fix a BC breaking change for PHP 5.6/PHPUnit 5.7.27 (#947)
## 1.2.1 (2019-02-07)
* Support for PHPUnit 8 (#942)
* Allow mocking static methods called on instance (#938)
- Support for PHPUnit 8 (#942)
- Allow mocking static methods called on instance (#938)
## 1.2.0 (2018-10-02)
* Starts counting default expectations towards count (#910)
* Adds workaround for some HHVM return types (#909)
* Adds PhpStorm metadata support for autocomplete etc (#904)
* Further attempts to support multiple PHPUnit versions (#903)
* Allows setting constructor expectations on instance mocks (#900)
* Adds workaround for HHVM memoization decorator (#893)
* Adds experimental support for callable spys (#712)
- Starts counting default expectations towards count (#910)
- Adds workaround for some HHVM return types (#909)
- Adds PhpStorm metadata support for autocomplete etc (#904)
- Further attempts to support multiple PHPUnit versions (#903)
- Allows setting constructor expectations on instance mocks (#900)
- Adds workaround for HHVM memoization decorator (#893)
- Adds experimental support for callable spys (#712)
## 1.1.0 (2018-05-08)
* Allows use of string method names in allows and expects (#794)
* Finalises allows and expects syntax in API (#799)
* Search for handlers in a case instensitive way (#801)
* Deprecate allowMockingMethodsUnnecessarily (#808)
* Fix risky tests (#769)
* Fix namespace in TestListener (#812)
* Fixed conflicting mock names (#813)
* Clean elses (#819)
* Updated protected method mocking exception message (#826)
* Map of constants to mock (#829)
* Simplify foreach with `in_array` function (#830)
* Typehinted return value on Expectation#verify. (#832)
* Fix shouldNotHaveReceived with HigherOrderMessage (#842)
* Deprecates shouldDeferMissing (#839)
* Adds support for return type hints in Demeter chains (#848)
* Adds shouldNotReceive to composite expectation (#847)
* Fix internal error when using --static-backup (#845)
* Adds `andAnyOtherArgs` as an optional argument matcher (#860)
* Fixes namespace qualifying with namespaced named mocks (#872)
* Added possibility to add Constructor-Expections on hard dependencies, read: Mockery::mock('overload:...') (#781)
- Allows use of string method names in allows and expects (#794)
- Finalises allows and expects syntax in API (#799)
- Search for handlers in a case instensitive way (#801)
- Deprecate allowMockingMethodsUnnecessarily (#808)
- Fix risky tests (#769)
- Fix namespace in TestListener (#812)
- Fixed conflicting mock names (#813)
- Clean elses (#819)
- Updated protected method mocking exception message (#826)
- Map of constants to mock (#829)
- Simplify foreach with `in_array` function (#830)
- Typehinted return value on Expectation#verify. (#832)
- Fix shouldNotHaveReceived with HigherOrderMessage (#842)
- Deprecates shouldDeferMissing (#839)
- Adds support for return type hints in Demeter chains (#848)
- Adds shouldNotReceive to composite expectation (#847)
- Fix internal error when using --static-backup (#845)
- Adds `andAnyOtherArgs` as an optional argument matcher (#860)
- Fixes namespace qualifying with namespaced named mocks (#872)
- Added possibility to add Constructor-Expections on hard dependencies, read: Mockery::mock('overload:...') (#781)
## 1.0.0 (2017-09-06)
* Destructors (`__destruct`) are stubbed out where it makes sense
* Allow passing a closure argument to `withArgs()` to validate multiple arguments at once.
* `Mockery\Adapter\Phpunit\TestListener` has been rewritten because it
- Destructors (`__destruct`) are stubbed out where it makes sense
- Allow passing a closure argument to `withArgs()` to validate multiple arguments at once.
- `Mockery\Adapter\Phpunit\TestListener` has been rewritten because it
incorrectly marked some tests as risky. It will no longer verify mock
expectations but instead check that tests do that themselves. PHPUnit 6 is
required if you want to use this fail safe.
* Removes SPL Class Loader
* Removed object recorder feature
* Bumped minimum PHP version to 5.6
* `andThrow` will now throw anything `\Throwable`
* Adds `allows` and `expects` syntax
* Adds optional global helpers for `mock`, `namedMock` and `spy`
* Adds ability to create objects using traits
* `Mockery\Matcher\MustBe` was deprecated
* Marked `Mockery\MockInterface` as internal
* Subset matcher matches recursively
* BC BREAK - Spies return `null` by default from ignored (non-mocked) methods with nullable return type
* Removed extracting getter methods of object instances
* BC BREAK - Remove implicit regex matching when trying to match string arguments, introduce `\Mockery::pattern()` when regex matching is needed
* Fix Mockery not getting closed in cases of failing test cases
* Fix Mockery not setting properties on overloaded instance mocks
* BC BREAK - Fix Mockery not trying default expectations if there is any concrete expectation
* BC BREAK - Mockery's PHPUnit integration will mark a test as risky if it
- Removes SPL Class Loader
- Removed object recorder feature
- Bumped minimum PHP version to 5.6
- `andThrow` will now throw anything `\Throwable`
- Adds `allows` and `expects` syntax
- Adds optional global helpers for `mock`, `namedMock` and `spy`
- Adds ability to create objects using traits
- `Mockery\Matcher\MustBe` was deprecated
- Marked `Mockery\MockInterface` as internal
- Subset matcher matches recursively
- BC BREAK - Spies return `null` by default from ignored (non-mocked) methods with nullable return type
- Removed extracting getter methods of object instances
- BC BREAK - Remove implicit regex matching when trying to match string arguments, introduce `\Mockery::pattern()` when regex matching is needed
- Fix Mockery not getting closed in cases of failing test cases
- Fix Mockery not setting properties on overloaded instance mocks
- BC BREAK - Fix Mockery not trying default expectations if there is any concrete expectation
- BC BREAK - Mockery's PHPUnit integration will mark a test as risky if it
thinks one it's exceptions has been swallowed in PHPUnit > 5.7.6. Use `$e->dismiss()` to dismiss.
## 0.9.4 (XXXX-XX-XX)
* `shouldIgnoreMissing` will respect global `allowMockingNonExistentMethods`
- `shouldIgnoreMissing` will respect global `allowMockingNonExistentMethods`
config
* Some support for variadic parameters
* Hamcrest is now a required dependency
* Instance mocks now respect `shouldIgnoreMissing` call on control instance
* This will be the *last version to support PHP 5.3*
* Added `Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration` trait
* Added `makePartial` to `Mockery\MockInterface` as it was missing
- Some support for variadic parameters
- Hamcrest is now a required dependency
- Instance mocks now respect `shouldIgnoreMissing` call on control instance
- This will be the *last version to support PHP 5.3*
- Added `Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration` trait
- Added `makePartial` to `Mockery\MockInterface` as it was missing
## 0.9.3 (2014-12-22)
* Added a basic spy implementation
* Added `Mockery\Adapter\Phpunit\MockeryTestCase` for more reliable PHPUnit
- Added a basic spy implementation
- Added `Mockery\Adapter\Phpunit\MockeryTestCase` for more reliable PHPUnit
integration
## 0.9.2 (2014-09-03)
* Some workarounds for the serialisation problems created by changes to PHP in 5.5.13, 5.4.29,
- Some workarounds for the serialisation problems created by changes to PHP in 5.5.13, 5.4.29,
5.6.
* Demeter chains attempt to reuse doubles as they see fit, so for foo->bar and
- Demeter chains attempt to reuse doubles as they see fit, so for foo->bar and
foo->baz, we'll attempt to use the same foo
## 0.9.1 (2014-05-02)
* Allow specifying consecutive exceptions to be thrown with `andThrowExceptions`
* Allow specifying methods which can be mocked when using
- Allow specifying consecutive exceptions to be thrown with `andThrowExceptions`
- Allow specifying methods which can be mocked when using
`Mockery\Configuration::allowMockingNonExistentMethods(false)` with
`Mockery\MockInterface::shouldAllowMockingMethod($methodName)`
* Added andReturnSelf method: `$mock->shouldReceive("foo")->andReturnSelf()`
* `shouldIgnoreMissing` now takes an optional value that will be return instead
- Added andReturnSelf method: `$mock->shouldReceive("foo")->andReturnSelf()`
- `shouldIgnoreMissing` now takes an optional value that will be return instead
of null, e.g. `$mock->shouldIgnoreMissing($mock)`
## 0.9.0 (2014-02-05)
* Allow mocking classes with final __wakeup() method
* Quick definitions are now always `byDefault`
* Allow mocking of protected methods with `shouldAllowMockingProtectedMethods`
* Support official Hamcrest package
* Generator completely rewritten
* Easily create named mocks with namedMock
- Allow mocking classes with final __wakeup() method
- Quick definitions are now always `byDefault`
- Allow mocking of protected methods with `shouldAllowMockingProtectedMethods`
- Support official Hamcrest package
- Generator completely rewritten
- Easily create named mocks with namedMock

View File

@@ -6,17 +6,15 @@ We'd love you to help out with mockery and no contribution is too small.
## Reporting Bugs
Issues can be reported on the [issue
tracker](https://github.com/padraic/mockery/issues). Please try and report any
bugs with a minimal reproducible example, it will make things easier for other
Issues can be reported on the [issue tracker](https://github.com/mockery/mockery/issues).
Please try and report any bugs with a minimal reproducible example, it will make things easier for other
contributors and your problems will hopefully be resolved quickly.
## Requesting Features
We're always interested to hear about your ideas and you can request features by
creating a ticket in the [issue
tracker](https://github.com/padraic/mockery/issues). We can't always guarantee
creating a ticket in the [issue tracker](https://github.com/mockery/mockery/issues). We can't always guarantee
someone will jump on it straight away, but putting it out there to see if anyone
else is interested is a good idea.
@@ -33,24 +31,20 @@ and
[PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) coding standards,
but we'll probably merge any code that looks close enough.
* Fork the [repository](https://github.com/padraic/mockery) on GitHub
* Fork the [repository](https://github.com/mockery/mockery) on GitHub
* Add the code for your feature or bug
* Add some tests for your feature or bug
* Optionally, but preferably, write some documentation
* Optionally, update the CHANGELOG.md file with your feature or
[BC](http://en.wikipedia.org/wiki/Backward_compatibility) break
* Send a [Pull
Request](https://help.github.com/articles/creating-a-pull-request) to the
* Send a [Pull Request](https://help.github.com/articles/creating-a-pull-request) to the
correct target branch (see below)
If you have a big change or would like to discuss something, create an issue in
the [issue tracker](https://github.com/padraic/mockery/issues) or jump in to
\#mockery on freenode
the [issue tracker](https://github.com/mockery/mockery/issues) or jump in to \#mockery on freenode
Any code you contribute must be licensed under the [BSD 3-Clause
License](http://opensource.org/licenses/BSD-3-Clause).
Any code you contribute must be licensed under the [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause).
## Target Branch
@@ -67,7 +61,7 @@ To run the unit tests for Mockery, clone the git repository, download Composer u
the instructions at [http://getcomposer.org/download/](http://getcomposer.org/download/),
then install the dependencies with `php /path/to/composer.phar install`.
This will install the required PHPUnit and Hamcrest dev dependencies and create the
This will install the required dev dependencies and create the
autoload files required by the unit tests. You may run the `vendor/bin/phpunit` command
to run the unit tests. If everything goes to plan, there will be no failed tests!

View File

@@ -1,27 +1,29 @@
Copyright (c) 2010, Pádraic Brady
BSD 3-Clause License
Copyright (c) 2009-2023, Pádraic Brady <padraic.brady@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of Pádraic Brady may not be used to endorse or promote
products derived from this software without specific prior written
permission.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -2,6 +2,9 @@ Mockery
=======
[![Build Status](https://github.com/mockery/mockery/actions/workflows/tests.yml/badge.svg)](https://github.com/mockery/mockery/actions)
[![Supported PHP Version](https://badgen.net/packagist/php/mockery/mockery?color=8892bf)](https://www.php.net/supported-versions)
[![Code Coverage](https://codecov.io/gh/mockery/mockery/branch/1.6.x/graph/badge.svg?token=oxHwVM56bT)](https://codecov.io/gh/mockery/mockery)
[![Type Coverage](https://shepherd.dev/github/mockery/mockery/coverage.svg)](https://shepherd.dev/github/mockery/mockery)
[![Latest Stable Version](https://poser.pugx.org/mockery/mockery/v/stable.svg)](https://packagist.org/packages/mockery/mockery)
[![Total Downloads](https://poser.pugx.org/mockery/mockery/downloads.svg)](https://packagist.org/packages/mockery/mockery)
@@ -167,7 +170,7 @@ $double->expects()->add($book)->twice();
If you have used Mockery before, you might see something new in the example
above &mdash; we created a method expectation using `expects`, instead of the "old"
`shouldReceive` syntax. This is a new feature of Mockery v1, but same as with
`accepts` in the previous section, it can be written in the "old" style.
`allows` in the previous section, it can be written in the "old" style.
For new users of Mockery, the above example can also be written as:

View File

@@ -1,9 +1,8 @@
{
"name": "mockery/mockery",
"description": "Mockery is a simple yet flexible PHP mock object framework",
"scripts": {
"docs": "phpdoc -d library -t docs/api"
},
"license": "BSD-3-Clause",
"type": "library",
"keywords": [
"bdd",
"library",
@@ -16,47 +15,105 @@
"test double",
"testing"
],
"homepage": "https://github.com/mockery/mockery",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
"homepage": "https://github.com/padraic",
"role": "Author"
},
{
"name": "Dave Marshall",
"email": "dave.marshall@atstsolutions.co.uk",
"homepage": "http://davedevelopment.co.uk"
"homepage": "https://davedevelopment.co.uk",
"role": "Developer"
},
{
"name": "Nathanael Esayeas",
"email": "nathanael.esayeas@protonmail.com",
"homepage": "https://github.com/ghostwriter",
"role": "Lead Developer"
}
],
"homepage": "https://github.com/mockery/mockery",
"support": {
"issues": "https://github.com/mockery/mockery/issues",
"source": "https://github.com/mockery/mockery",
"docs": "https://docs.mockery.io/",
"rss": "https://github.com/mockery/mockery/releases.atom",
"security": "https://github.com/mockery/mockery/security/advisories"
},
"require": {
"php": "^7.3 || ^8.0",
"php": ">=7.3",
"lib-pcre": ">=7.0",
"hamcrest/hamcrest-php": "^2.0.1"
},
"require-dev": {
"phpunit/phpunit": "^8.5 || ^9.3"
"phpunit/phpunit": "^8.5 || ^9.6.17",
"symplify/easy-coding-standard": "^12.1.14"
},
"conflict": {
"phpunit/phpunit": "<8.0"
},
"autoload": {
"psr-0": {
"Mockery": "library/"
}
"psr-4": {
"Mockery\\": "library/Mockery"
},
"files": [
"library/helpers.php",
"library/Mockery.php"
]
},
"autoload-dev": {
"psr-4": {
"Fixture\\": "tests/Fixture/",
"Mockery\\Tests\\Unit\\": "tests/Unit",
"test\\": "tests/"
}
},
"files": [
"fixtures/autoload.php",
"vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php"
]
},
"config": {
"preferred-install": "dist"
"optimize-autoloader": true,
"platform": {
"php": "7.3.999"
},
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
"scripts": {
"check": [
"@composer validate",
"@ecs",
"@test"
],
"docs": "vendor/bin/phpdoc -d library -t docs/api",
"ecs": [
"@ecs:fix",
"@ecs:check"
],
"ecs:check": "ecs check --clear-cache || true",
"ecs:fix": "ecs check --clear-cache --fix",
"phive": [
"tools/phive update --force-accept-unsigned",
"tools/phive purge"
],
"phpunit": "vendor/bin/phpunit --do-not-cache-result --colors=always",
"phpunit:coverage": "@phpunit --coverage-clover=coverage.xml",
"psalm": "tools/psalm --no-cache --show-info=true",
"psalm:alter": "tools/psalm --no-cache --alter --allow-backwards-incompatible-changes=false --safe-types",
"psalm:baseline": "@psalm --no-diff --set-baseline=psalm-baseline.xml",
"psalm:dry-run": "@psalm:alter --issues=all --dry-run",
"psalm:fix": "@psalm:alter --issues=UnnecessaryVarAnnotation,MissingPureAnnotation,MissingImmutableAnnotation",
"psalm:security": "@psalm --no-diff --taint-analysis",
"psalm:shepherd": "@psalm --no-diff --shepherd --stats --output-format=github",
"test": [
"@phpunit --stop-on-defect",
"@psalm",
"@psalm:security",
"@psalm:dry-run"
]
}
}

View File

@@ -30,6 +30,7 @@ import os
# ones.
extensions = [
'sphinx.ext.todo',
'sphinx_rtd_theme',
]
# Add any paths that contain templates here, relative to this directory.
@@ -53,9 +54,9 @@ copyright = u'Pádraic Brady, Dave Marshall and contributors'
# built documents.
#
# The short X.Y version.
version = '1.0'
version = '1.6'
# The full version, including alpha/beta/rc tags.
release = '1.0-alpha'
release = '1.6.x'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -100,7 +101,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -256,7 +257,7 @@ if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
print sphinx_rtd_theme.get_html_theme_path()
print(sphinx_rtd_theme.get_html_theme_path())
# load PhpLexer
from sphinx.highlighting import lexers

View File

@@ -30,7 +30,7 @@ Read the documentation for a detailed overview of ":doc:`/reference/phpunit_inte
+++++++++++++++++++++++++++++++++++++++++
As of 1.0.0 the ``\Mockery\Matcher\MustBe`` matcher is deprecated and will be removed in
Mockery 2.0.0. We recommend instead to use the PHPUnit or Hamcrest equivalents of the
Mockery 2.0.0. We recommend instead to use the PHPUnit equivalents of the
MustBe matcher.
``allows`` and ``expects``

View File

@@ -419,7 +419,7 @@ additional modifier:
\Mockery::mock('MyClass')->shouldIgnoreMissing()->asUndefined();
The returned object is nothing more than a placeholder so if, by some act of
fate, it's erroneously used somewhere it shouldn't it will likely not pass a
fate, it's erroneously used somewhere it shouldn't, it will likely not pass a
logic check.
We have encountered the ``makePartial()`` method before, as it is the method we

View File

@@ -448,6 +448,34 @@ This is actually identical to using ``atLeast()->times($min)->atMost()->times($m
but is provided as a shorthand. It may be followed by a ``times()`` call with no
parameter to preserve the APIs natural language readability.
Multiple Calls with Different Expectations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If a method is expected to get called multiple times with different arguments
and/or return values we can simply repeat the expectations. The same of course
also works if we expect multiple calls to different methods.
.. code-block:: php
$mock = \Mockery::mock('MyClass');
// Expectations for the 1st call
$mock->shouldReceive('name_of_method')
->once()
->with('arg1')
->andReturn($value1)
// 2nd call to same method
->shouldReceive('name_of_method')
->once()
->with('arg2')
->andReturn($value2)
// final call to another method
->shouldReceive('other_method')
->once()
->with('other')
->andReturn($value_other);
Expectation Declaration Utilities
---------------------------------

View File

@@ -9,6 +9,7 @@ Reference
argument_validation
alternative_should_receive_syntax
spies
instance_mocking
partial_mocks
protected_methods
public_properties

View File

@@ -17,8 +17,8 @@ our tests more clear.
Spies also allow us to follow the more familiar Arrange-Act-Assert or
Given-When-Then style within our tests. With mocks, we have to follow a less
familiar style, something along the lines of Arrange-Expect-Act-Assert, where
we have to tell our mocks what to expect before we act on the sut, then assert
that those expectations where met:
we have to tell our mocks what to expect before we act on the SUT, then assert
that those expectations were met:
.. code-block:: php

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,20 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Adapter\Phpunit;
use Mockery;
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
use function method_exists;
/**
* Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
@@ -32,6 +26,30 @@ trait MockeryPHPUnitIntegration
protected $mockeryOpen;
protected function addMockeryExpectationsToAssertionCount()
{
$this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount());
}
protected function checkMockeryExceptions()
{
if (! method_exists($this, 'markAsRisky')) {
return;
}
foreach (Mockery::getContainer()->mockery_thrownExceptions() as $e) {
if (! $e->dismissed()) {
$this->markAsRisky();
}
}
}
protected function closeMockery()
{
Mockery::close();
$this->mockeryOpen = false;
}
/**
* Performs assertions shared by all tests of a test case. This method is
* called before execution of a test ends and before the tearDown method.
@@ -45,41 +63,10 @@ trait MockeryPHPUnitIntegration
parent::assertPostConditions();
}
protected function addMockeryExpectationsToAssertionCount()
{
$this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount());
}
protected function checkMockeryExceptions()
{
if (!method_exists($this, "markAsRisky")) {
return;
}
foreach (Mockery::getContainer()->mockery_thrownExceptions() as $e) {
if (!$e->dismissed()) {
$this->markAsRisky();
}
}
}
protected function closeMockery()
{
Mockery::close();
$this->mockeryOpen = false;
}
/**
* @before
*/
protected function startMockery()
{
$this->mockeryOpen = true;
}
/**
* @after
*/
#[After]
protected function purgeMockeryContainer()
{
if ($this->mockeryOpen) {
@@ -87,4 +74,13 @@ trait MockeryPHPUnitIntegration
Mockery::close();
}
}
/**
* @before
*/
#[Before]
protected function startMockery()
{
$this->mockeryOpen = true;
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
declare(strict_types=1);

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Adapter\Phpunit;
abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
use PHPUnit\Framework\TestCase;
abstract class MockeryTestCase extends TestCase
{
use MockeryPHPUnitIntegration;
use MockeryTestCaseSetUp;

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2019 Enalean
* @license https://github.com/mockery/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
declare(strict_types=1);

View File

@@ -1,29 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Adapter\Phpunit;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
class TestListener implements PHPUnitTestListener
{

View File

@@ -1,30 +1,27 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Adapter\Phpunit;
use LogicException;
use Mockery;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Util\Blacklist;
use PHPUnit\Runner\BaseTestRunner;
use PHPUnit\Util\Blacklist;
use ReflectionClass;
use function dirname;
use function method_exists;
use function sprintf;
class TestListenerTrait
{
@@ -37,7 +34,7 @@ class TestListenerTrait
*/
public function endTest(Test $test, $time)
{
if (!$test instanceof TestCase) {
if (! $test instanceof TestCase) {
// We need the getTestResultObject and getStatus methods which are
// not part of the interface.
return;
@@ -54,13 +51,13 @@ class TestListenerTrait
try {
// The self() call is used as a sentinel. Anything that throws if
// the container is closed already will do.
\Mockery::self();
} catch (\LogicException $_) {
Mockery::self();
} catch (LogicException $logicException) {
return;
}
$e = new ExpectationFailedException(
\sprintf(
sprintf(
"Mockery's expectations have not been verified. Make sure that \Mockery::close() is called at the end of the test. Consider using %s\MockeryPHPUnitIntegration or extending %s\MockeryTestCase.",
__NAMESPACE__,
__NAMESPACE__
@@ -78,10 +75,10 @@ class TestListenerTrait
public function startTestSuite()
{
if (method_exists(Blacklist::class, 'addDirectory')) {
(new BlackList())->getBlacklistedDirectories();
Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName()));
(new Blacklist())->getBlacklistedDirectories();
Blacklist::addDirectory(dirname((new ReflectionClass(Mockery::class))->getFileName()));
} else {
Blacklist::$blacklistedClassNames[\Mockery::class] = 1;
Blacklist::$blacklistedClassNames[Mockery::class] = 1;
}
}
}

View File

@@ -1,27 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Mockery\Matcher\Closure;
use Closure;
use function func_get_args;
/**
* @internal
@@ -30,13 +21,16 @@ class ClosureWrapper
{
private $closure;
public function __construct(\Closure $closure)
public function __construct(Closure $closure)
{
$this->closure = $closure;
}
/**
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
return ($this->closure)(...func_get_args());
}
}

View File

@@ -1,38 +1,64 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use function array_map;
use function current;
use function implode;
use function reset;
class CompositeExpectation implements ExpectationInterface
{
/**
* Stores an array of all expectations for this composite
*
* @var array
* @var array<ExpectationInterface>
*/
protected $_expectations = array();
protected $_expectations = [];
/**
* Intercept any expectation calls and direct against all expectations
*
* @param string $method
*
* @return self
*/
public function __call($method, array $args)
{
foreach ($this->_expectations as $expectation) {
$expectation->{$method}(...$args);
}
return $this;
}
/**
* Return the string summary of this composite expectation
*
* @return string
*/
public function __toString()
{
$parts = array_map(static function (ExpectationInterface $expectation): string {
return (string) $expectation;
}, $this->_expectations);
return '[' . implode(', ', $parts) . ']';
}
/**
* Add an expectation to the composite
*
* @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation
* @param ExpectationInterface|HigherOrderMessage $expectation
*
* @return void
*/
public function add($expectation)
@@ -52,26 +78,24 @@ class CompositeExpectation implements ExpectationInterface
* Set a return value, or sequential queue of return values
*
* @param mixed ...$args
*
* @return self
*/
public function andReturns(...$args)
{
return call_user_func_array([$this, 'andReturn'], $args);
return $this->andReturn(...$args);
}
/**
* Intercept any expectation calls and direct against all expectations
* Return the parent mock of the first expectation
*
* @param string $method
* @param array $args
* @return self
* @return LegacyMockInterface&MockInterface
*/
public function __call($method, array $args)
public function getMock()
{
foreach ($this->_expectations as $expectation) {
call_user_func_array(array($expectation, $method), $args);
}
return $this;
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock();
}
/**
@@ -86,22 +110,10 @@ class CompositeExpectation implements ExpectationInterface
return $first->getOrderNumber();
}
/**
* Return the parent mock of the first expectation
*
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
public function getMock()
{
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock();
}
/**
* Mockery API alias to getMock
*
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
* @return LegacyMockInterface&MockInterface
*/
public function mock()
{
@@ -109,46 +121,30 @@ class CompositeExpectation implements ExpectationInterface
}
/**
* Starts a new expectation addition on the first mock which is the primary
* target outside of a demeter chain
* Starts a new expectation addition on the first mock which is the primary target outside of a demeter chain
*
* @param mixed ...$args
* @return \Mockery\Expectation
*/
public function shouldReceive(...$args)
{
reset($this->_expectations);
$first = current($this->_expectations);
return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args);
}
/**
* Starts a new expectation addition on the first mock which is the primary
* target outside of a demeter chain
*
* @param mixed ...$args
* @return \Mockery\Expectation
* @return Expectation
*/
public function shouldNotReceive(...$args)
{
reset($this->_expectations);
$first = current($this->_expectations);
return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args);
return $first->getMock()->shouldNotReceive(...$args);
}
/**
* Return the string summary of this composite expectation
* Starts a new expectation addition on the first mock which is the primary target, outside of a demeter chain
*
* @return string
* @param mixed ...$args
*
* @return Expectation
*/
public function __toString()
public function shouldReceive(...$args)
{
$return = '[';
$parts = array();
foreach ($this->_expectations as $exp) {
$parts[] = (string) $exp;
}
$return .= implode(', ', $parts) . ']';
return $return;
reset($this->_expectations);
$first = current($this->_expectations);
return $first->getMock()->shouldReceive(...$args);
}
}

View File

@@ -1,35 +1,36 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Closure;
use Hamcrest\Matcher;
use Hamcrest_Matcher;
use InvalidArgumentException;
use LogicException;
use Mockery\Matcher\MatcherInterface;
use function array_key_exists;
use function array_merge;
use function class_implements;
use function get_parent_class;
use function is_a;
use function sprintf;
use function strtolower;
use function trigger_error;
use const E_USER_DEPRECATED;
use const PHP_MAJOR_VERSION;
class Configuration
{
/**
* Boolean assertion of whether we can mock methods which do not actually
* exist for the given class or object (ignored for unreal mocks)
*
* @var bool
*/
protected $_allowMockingNonExistentMethod = true;
/**
* Boolean assertion of whether we ignore unnecessary mocking of methods,
* i.e. when method expectations are made, set using a zeroOrMoreTimes()
@@ -41,18 +42,53 @@ class Configuration
protected $_allowMockingMethodsUnnecessarily = true;
/**
* @var QuickDefinitionsConfiguration
* Boolean assertion of whether we can mock methods which do not actually
* exist for the given class or object (ignored for unreal mocks)
*
* @var bool
*/
protected $_quickDefinitionsConfiguration;
protected $_allowMockingNonExistentMethod = true;
/**
* Constants map
*
* e.g. ['class' => ['MY_CONST' => 123, 'OTHER_CONST' => 'foo']]
*
* @var array<class-string,array<string,array<scalar>|scalar>>
*/
protected $_constantsMap = [];
/**
* Default argument matchers
*
* e.g. ['class' => 'matcher']
*
* @var array<class-string,class-string>
*/
protected $_defaultMatchers = [];
/**
* Parameter map for use with PHP internal classes.
*
* @var array
* e.g. ['class' => ['method' => ['param1', 'param2']]]
*
* @var array<class-string,array<string,list<string>>>
*/
protected $_internalClassParamMap = array();
protected $_internalClassParamMap = [];
protected $_constantsMap = array();
/**
* Custom object formatters
*
* e.g. ['class' => static fn($object) => 'formatted']
*
* @var array<class-string,Closure>
*/
protected $_objectFormatters = [];
/**
* @var QuickDefinitionsConfiguration
*/
protected $_quickDefinitionsConfiguration;
/**
* Boolean assertion is reflection caching enabled or not. It should be
@@ -67,129 +103,35 @@ class Configuration
$this->_quickDefinitionsConfiguration = new QuickDefinitionsConfiguration();
}
/**
* Custom object formatters
*
* @var array
*/
protected $_objectFormatters = array();
/**
* Default argument matchers
*
* @var array
*/
protected $_defaultMatchers = array();
/**
* Set boolean to allow/prevent mocking of non-existent methods
*
* @param bool $flag
*/
public function allowMockingNonExistentMethods($flag = true)
{
$this->_allowMockingNonExistentMethod = (bool) $flag;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*/
public function mockingNonExistentMethodsAllowed()
{
return $this->_allowMockingNonExistentMethod;
}
/**
* Set boolean to allow/prevent unnecessary mocking of methods
*
* @param bool $flag
*
* @return void
*
* @deprecated since 1.4.0
*/
public function allowMockingMethodsUnnecessarily($flag = true)
{
@trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED);
@trigger_error(
sprintf('The %s method is deprecated and will be removed in a future version of Mockery', __METHOD__),
E_USER_DEPRECATED
);
$this->_allowMockingMethodsUnnecessarily = (bool) $flag;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
* Set boolean to allow/prevent mocking of non-existent methods
*
* @return bool
* @param bool $flag
*
* @deprecated since 1.4.0
* @return void
*/
public function mockingMethodsUnnecessarilyAllowed()
public function allowMockingNonExistentMethods($flag = true)
{
@trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED);
return $this->_allowMockingMethodsUnnecessarily;
}
/**
* Set a parameter map (array of param signature strings) for the method
* of an internal PHP class.
*
* @param string $class
* @param string $method
* @param array $map
*/
public function setInternalClassMethodParamMap($class, $method, array $map)
{
if (\PHP_MAJOR_VERSION > 7) {
throw new \LogicException('Internal class parameter overriding is not available in PHP 8. Incompatible signatures have been reclassified as fatal errors.');
}
if (!isset($this->_internalClassParamMap[strtolower($class)])) {
$this->_internalClassParamMap[strtolower($class)] = array();
}
$this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map;
}
/**
* Remove all overridden parameter maps from internal PHP classes.
*/
public function resetInternalClassMethodParamMaps()
{
$this->_internalClassParamMap = array();
}
/**
* Get the parameter map of an internal PHP class method
*
* @return array|null
*/
public function getInternalClassMethodParamMap($class, $method)
{
if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) {
return $this->_internalClassParamMap[strtolower($class)][strtolower($method)];
}
}
public function getInternalClassMethodParamMaps()
{
return $this->_internalClassParamMap;
}
public function setConstantsMap(array $map)
{
$this->_constantsMap = $map;
}
public function getConstantsMap()
{
return $this->_constantsMap;
}
/**
* Returns the quick definitions configuration
*/
public function getQuickDefinitions(): QuickDefinitionsConfiguration
{
return $this->_quickDefinitionsConfiguration;
$this->_allowMockingNonExistentMethod = (bool) $flag;
}
/**
@@ -199,6 +141,8 @@ class Configuration
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*
* @return void
*/
public function disableReflectionCache()
{
@@ -212,72 +156,251 @@ class Configuration
* PHPUnit's --static-backup option.
*
* @see https://github.com/mockery/mockery/issues/268
*
* @return void
*/
public function enableReflectionCache()
{
$this->_reflectionCacheEnabled = true;
}
/**
* Get the map of constants to be used in the mock generator
*
* @return array<class-string,array<string,array<scalar>|scalar>>
*/
public function getConstantsMap()
{
return $this->_constantsMap;
}
/**
* Get the default matcher for a given class
*
* @param class-string $class
*
* @return null|class-string
*/
public function getDefaultMatcher($class)
{
$classes = [];
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass !== false);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (array_key_exists($type, $this->_defaultMatchers)) {
return $this->_defaultMatchers[$type];
}
}
return null;
}
/**
* Get the parameter map of an internal PHP class method
*
* @param class-string $class
* @param string $method
*
* @return null|array
*/
public function getInternalClassMethodParamMap($class, $method)
{
$class = strtolower($class);
$method = strtolower($method);
if (! array_key_exists($class, $this->_internalClassParamMap)) {
return null;
}
if (! array_key_exists($method, $this->_internalClassParamMap[$class])) {
return null;
}
return $this->_internalClassParamMap[$class][$method];
}
/**
* Get the parameter maps of internal PHP classes
*
* @return array<class-string,array<string,list<string>>>
*/
public function getInternalClassMethodParamMaps()
{
return $this->_internalClassParamMap;
}
/**
* Get the object formatter for a class
*
* @param class-string $class
* @param Closure $defaultFormatter
*
* @return Closure
*/
public function getObjectFormatter($class, $defaultFormatter)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass !== false);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (array_key_exists($type, $this->_objectFormatters)) {
return $this->_objectFormatters[$type];
}
}
return $defaultFormatter;
}
/**
* Returns the quick definitions configuration
*/
public function getQuickDefinitions(): QuickDefinitionsConfiguration
{
return $this->_quickDefinitionsConfiguration;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*
* @deprecated since 1.4.0
*/
public function mockingMethodsUnnecessarilyAllowed()
{
@trigger_error(
sprintf('The %s method is deprecated and will be removed in a future version of Mockery', __METHOD__),
E_USER_DEPRECATED
);
return $this->_allowMockingMethodsUnnecessarily;
}
/**
* Return flag indicating whether mocking non-existent methods allowed
*
* @return bool
*/
public function mockingNonExistentMethodsAllowed()
{
return $this->_allowMockingNonExistentMethod;
}
/**
* Is reflection cache enabled?
*
* @return bool
*/
public function reflectionCacheEnabled()
{
return $this->_reflectionCacheEnabled;
}
/**
* Remove all overridden parameter maps from internal PHP classes.
*
* @return void
*/
public function resetInternalClassMethodParamMaps()
{
$this->_internalClassParamMap = [];
}
/**
* Set a map of constants to be used in the mock generator
*
* e.g. ['MyClass' => ['MY_CONST' => 123, 'ARRAY_CONST' => ['foo', 'bar']]]
*
* @param array<class-string,array<string,array<scalar>|scalar>> $map
*
* @return void
*/
public function setConstantsMap(array $map)
{
$this->_constantsMap = $map;
}
/**
* @param class-string $class
* @param class-string $matcherClass
*
* @throws InvalidArgumentException
*
* @return void
*/
public function setDefaultMatcher($class, $matcherClass)
{
$isHamcrest = is_a($matcherClass, Matcher::class, true)
|| is_a($matcherClass, Hamcrest_Matcher::class, true);
if ($isHamcrest) {
@trigger_error('Hamcrest package has been deprecated and will be removed in 2.0', E_USER_DEPRECATED);
}
if (! $isHamcrest && ! is_a($matcherClass, MatcherInterface::class, true)) {
throw new InvalidArgumentException(sprintf(
"Matcher class must implement %s, '%s' given.",
MatcherInterface::class,
$matcherClass
));
}
$this->_defaultMatchers[$class] = $matcherClass;
}
/**
* Set a parameter map (array of param signature strings) for the method of an internal PHP class.
*
* @param class-string $class
* @param string $method
* @param list<string> $map
*
* @throws LogicException
*
* @return void
*/
public function setInternalClassMethodParamMap($class, $method, array $map)
{
if (PHP_MAJOR_VERSION > 7) {
throw new LogicException(
'Internal class parameter overriding is not available in PHP 8. Incompatible signatures have been reclassified as fatal errors.'
);
}
$class = strtolower($class);
if (! array_key_exists($class, $this->_internalClassParamMap)) {
$this->_internalClassParamMap[$class] = [];
}
$this->_internalClassParamMap[$class][strtolower($method)] = $map;
}
/**
* Set a custom object formatter for a class
*
* @param class-string $class
* @param Closure $formatterCallback
*
* @return void
*/
public function setObjectFormatter($class, $formatterCallback)
{
$this->_objectFormatters[$class] = $formatterCallback;
}
public function getObjectFormatter($class, $defaultFormatter)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_objectFormatters[$type])) {
return $this->_objectFormatters[$type];
}
}
return $defaultFormatter;
}
/**
* @param string $class
* @param string $matcherClass
*/
public function setDefaultMatcher($class, $matcherClass)
{
if (!is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) &&
!is_a($matcherClass, \Hamcrest\Matcher::class, true) &&
!is_a($matcherClass, \Hamcrest_Matcher::class, true)
) {
throw new \InvalidArgumentException(
"Matcher class must be either Hamcrest matcher or extend \Mockery\Matcher\MatcherAbstract, " .
"'$matcherClass' given."
);
}
$this->_defaultMatchers[$class] = $matcherClass;
}
public function getDefaultMatcher($class)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_defaultMatchers[$type])) {
return $this->_defaultMatchers[$type];
}
}
return null;
}
}

View File

@@ -1,39 +1,63 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Closure;
use Exception as PHPException;
use Mockery;
use Mockery\Exception\InvalidOrderException;
use Mockery\Exception\RuntimeException;
use Mockery\Generator\Generator;
use Mockery\Generator\MockConfigurationBuilder;
use Mockery\Loader\Loader as LoaderInterface;
use ReflectionClass;
use ReflectionException;
use Throwable;
use function array_filter;
use function array_key_exists;
use function array_keys;
use function array_pop;
use function array_shift;
use function array_values;
use function class_exists;
use function count;
use function explode;
use function get_class;
use function interface_exists;
use function is_callable;
use function is_object;
use function is_string;
use function md5;
use function preg_grep;
use function preg_match;
use function range;
use function reset;
use function rtrim;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trait_exists;
/**
* Container for mock objects
*
* @template TMockObject of object
*/
class Container
{
const BLOCKS = \Mockery::BLOCKS;
/**
* Store of mock objects
*
* @var array
*/
protected $_mocks = array();
public const BLOCKS = Mockery::BLOCKS;
/**
* Order number of allocation
@@ -49,32 +73,136 @@ class Container
*/
protected $_currentOrder = 0;
/**
* Ordered groups
*
* @var array
*/
protected $_groups = array();
/**
* @var Generator
*/
protected $_generator;
/**
* Ordered groups
*
* @var array<string,int>
*/
protected $_groups = [];
/**
* @var LoaderInterface
*/
protected $_loader;
/**
* @var array
* Store of mock objects
*
* @var array<class-string<LegacyMockInterface&MockInterface&TMockObject>|array-key,LegacyMockInterface&MockInterface&TMockObject>
*/
protected $_namedMocks = array();
protected $_mocks = [];
public function __construct(Generator $generator = null, LoaderInterface $loader = null)
/**
* @var array<string,string>
*/
protected $_namedMocks = [];
/**
* @var Instantiator
*/
protected $instantiator;
public function __construct(?Generator $generator = null, ?LoaderInterface $loader = null, ?Instantiator $instantiator = null)
{
$this->_generator = $generator ?: \Mockery::getDefaultGenerator();
$this->_loader = $loader ?: \Mockery::getDefaultLoader();
$this->_generator = $generator instanceof Generator ? $generator : Mockery::getDefaultGenerator();
$this->_loader = $loader instanceof LoaderInterface ? $loader : Mockery::getDefaultLoader();
$this->instantiator = $instantiator instanceof Instantiator ? $instantiator : new Instantiator();
}
/**
* Return a specific remembered mock according to the array index it
* was stored to in this container instance
*
* @template TMock of object
*
* @param class-string<TMock> $reference
*
* @return null|(LegacyMockInterface&MockInterface&TMock)
*/
public function fetchMock($reference)
{
return $this->_mocks[$reference] ?? null;
}
/**
* @return Generator
*/
public function getGenerator()
{
return $this->_generator;
}
/**
* @param string $method
* @param string $parent
*
* @return null|string
*/
public function getKeyOfDemeterMockFor($method, $parent)
{
$keys = array_keys($this->_mocks);
$match = preg_grep('/__demeter_' . md5($parent) . sprintf('_%s$/', $method), $keys);
if ($match === false) {
return null;
}
if ($match === []) {
return null;
}
return array_values($match)[0];
}
/**
* @return LoaderInterface
*/
public function getLoader()
{
return $this->_loader;
}
/**
* @template TMock of object
* @return array<class-string<LegacyMockInterface&MockInterface&TMockObject>|array-key,LegacyMockInterface&MockInterface&TMockObject>
*/
public function getMocks()
{
return $this->_mocks;
}
/**
* @return void
*/
public function instanceMock()
{
}
/**
* see http://php.net/manual/en/language.oop5.basic.php
*
* @param string $className
*
* @return bool
*/
public function isValidClassName($className)
{
if ($className[0] === '\\') {
$className = substr($className, 1); // remove the first backslash
}
// all the namespaces and class name should match the regex
return array_filter(
explode('\\', $className),
static function ($name): bool {
return ! preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
}
) === [];
}
/**
@@ -85,119 +213,179 @@ class Container
* names or partials - just so long as it's something that can be mocked.
* I'll refactor it one day so it's easier to follow.
*
* @param array ...$args
* @template TMock of object
*
* @return Mock
* @throws Exception\RuntimeException
* @param array<class-string<TMock>|TMock|Closure(LegacyMockInterface&MockInterface&TMock):LegacyMockInterface&MockInterface&TMock|array<TMock>> $args
*
* @throws ReflectionException|RuntimeException
*
* @return LegacyMockInterface&MockInterface&TMock
*/
public function mock(...$args)
{
/** @var null|MockConfigurationBuilder $builder */
$builder = null;
/** @var null|callable $expectationClosure */
$expectationClosure = null;
$quickdefs = array();
$partialMethods = null;
$quickDefinitions = [];
$constructorArgs = null;
$blocks = array();
$class = null;
$blocks = [];
if (count($args) > 1) {
$finalArg = end($args);
reset($args);
$finalArg = array_pop($args);
if (is_callable($finalArg) && is_object($finalArg)) {
$expectationClosure = array_pop($args);
$expectationClosure = $finalArg;
} else {
$args[] = $finalArg;
}
}
$builder = new MockConfigurationBuilder();
foreach ($args as $k => $arg) {
if ($arg instanceof MockConfigurationBuilder) {
$builder = $arg;
unset($args[$k]);
}
}
reset($args);
$builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps());
$builder->setConstantsMap(\Mockery::getConfiguration()->getConstantsMap());
$builder = $builder ?? new MockConfigurationBuilder();
$mockeryConfiguration = Mockery::getConfiguration();
$builder->setParameterOverrides($mockeryConfiguration->getInternalClassMethodParamMaps());
$builder->setConstantsMap($mockeryConfiguration->getConstantsMap());
while (count($args) > 0) {
while ($args !== []) {
$arg = array_shift($args);
// check for multiple interfaces
if (is_string($arg)) {
foreach (explode('|', $arg) as $type) {
if ($arg === 'null') {
// skip PHP 8 'null's
} elseif (strpos($type, ',') && !strpos($type, ']')) {
continue;
}
if (strpos($type, ',') && !strpos($type, ']')) {
$interfaces = explode(',', str_replace(' ', '', $type));
$builder->addTargets($interfaces);
} elseif (substr($type, 0, 6) == 'alias:') {
continue;
}
if (strpos($type, 'alias:') === 0) {
$type = str_replace('alias:', '', $type);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, 0, 9) == 'overload:') {
continue;
}
if (strpos($type, 'overload:') === 0) {
$type = str_replace('overload:', '', $type);
$builder->setInstanceMock(true);
$builder->addTarget('stdClass');
$builder->setName($type);
} elseif (substr($type, strlen($type)-1, 1) == ']') {
continue;
}
if ($type[strlen($type) - 1] === ']') {
$parts = explode('[', $type);
if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) {
throw new \Mockery\Exception('Can only create a partial mock from'
. ' an existing class or interface');
}
$class = $parts[0];
$parts[1] = str_replace(' ', '', $parts[1]);
$partialMethods = array_filter(explode(',', strtolower(rtrim($parts[1], ']'))));
if (! class_exists($class, true) && ! interface_exists($class, true)) {
throw new Exception('Can only create a partial mock from an existing class or interface');
}
$builder->addTarget($class);
$partialMethods = array_filter(
explode(',', strtolower(rtrim(str_replace(' ', '', $parts[1]), ']')))
);
foreach ($partialMethods as $partialMethod) {
if ($partialMethod[0] === '!') {
$builder->addBlackListedMethod(substr($partialMethod, 1));
continue;
}
$builder->addWhiteListedMethod($partialMethod);
}
} elseif (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) {
$builder->addTarget($type);
} elseif (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() && (!class_exists($type, true) && !interface_exists($type, true))) {
throw new \Mockery\Exception("Mockery can't find '$type' so can't mock it");
} else {
if (!$this->isValidClassName($type)) {
throw new \Mockery\Exception('Class name contains invalid characters');
}
$builder->addTarget($type);
continue;
}
break; // unions are "sum" types and not "intersections", and so we must only process the first part
if (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) {
$builder->addTarget($type);
continue;
}
if (! $mockeryConfiguration->mockingNonExistentMethodsAllowed()) {
throw new Exception(sprintf("Mockery can't find '%s' so can't mock it", $type));
}
if (! $this->isValidClassName($type)) {
throw new Exception('Class name contains invalid characters');
}
$builder->addTarget($type);
// unions are "sum" types and not "intersections", and so we must only process the first part
break;
}
} elseif (is_object($arg)) {
continue;
}
if (is_object($arg)) {
$builder->addTarget($arg);
} elseif (is_array($arg)) {
if (!empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) {
continue;
}
if (is_array($arg)) {
if ([] !== $arg && array_keys($arg) !== range(0, count($arg) - 1)) {
// if associative array
if (array_key_exists(self::BLOCKS, $arg)) {
$blocks = $arg[self::BLOCKS];
}
unset($arg[self::BLOCKS]);
$quickdefs = $arg;
} else {
$constructorArgs = $arg;
$quickDefinitions = $arg;
continue;
}
} else {
throw new \Mockery\Exception(
'Unable to parse arguments sent to '
. get_class($this) . '::mock()'
);
$constructorArgs = $arg;
continue;
}
throw new Exception(sprintf(
'Unable to parse arguments sent to %s::mock()', get_class($this)
));
}
$builder->addBlackListedMethods($blocks);
if (!is_null($constructorArgs)) {
$builder->addBlackListedMethod("__construct"); // we need to pass through
if ($constructorArgs !== null) {
$builder->addBlackListedMethod('__construct'); // we need to pass through
} else {
$builder->setMockOriginalDestructor(true);
}
if (!empty($partialMethods) && $constructorArgs === null) {
$constructorArgs = array();
if ($partialMethods !== null && $constructorArgs === null) {
$constructorArgs = [];
}
$config = $builder->getMockConfiguration();
@@ -206,114 +394,44 @@ class Container
$def = $this->getGenerator()->generate($config);
if (class_exists($def->getClassName(), $attemptAutoload = false)) {
$rfc = new \ReflectionClass($def->getClassName());
if (!$rfc->implementsInterface("Mockery\LegacyMockInterface")) {
throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists");
$className = $def->getClassName();
if (class_exists($className, $attemptAutoload = false)) {
$rfc = new ReflectionClass($className);
if (! $rfc->implementsInterface(LegacyMockInterface::class)) {
throw new RuntimeException(sprintf('Could not load mock %s, class already exists', $className));
}
}
$this->getLoader()->load($def);
$mock = $this->_getInstance($def->getClassName(), $constructorArgs);
$mock = $this->_getInstance($className, $constructorArgs);
$mock->mockery_init($this, $config->getTargetObject(), $config->isInstanceMock());
if (!empty($quickdefs)) {
if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickdefs)->atLeast()->once();
if ($quickDefinitions !== []) {
if ($mockeryConfiguration->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickDefinitions)->atLeast()->once();
} else {
$mock->shouldReceive($quickdefs)->byDefault();
$mock->shouldReceive($quickDefinitions)->byDefault();
}
}
if (!empty($expectationClosure)) {
// if the last parameter passed to mock() is a closure,
if ($expectationClosure instanceof Closure) {
// call the closure with the mock object
$expectationClosure($mock);
}
$this->rememberMock($mock);
return $mock;
}
public function instanceMock()
{
}
public function getLoader()
{
return $this->_loader;
}
public function getGenerator()
{
return $this->_generator;
return $this->rememberMock($mock);
}
/**
* @param string $method
* @param string $parent
* @return string|null
*/
public function getKeyOfDemeterMockFor($method, $parent)
{
$keys = array_keys($this->_mocks);
$match = preg_grep("/__demeter_" . md5($parent) . "_{$method}$/", $keys);
if (count($match) == 1) {
$res = array_values($match);
if (count($res) > 0) {
return $res[0];
}
}
return null;
}
/**
* @return array
*/
public function getMocks()
{
return $this->_mocks;
}
/**
* Tear down tasks for this container
* Fetch the next available allocation order number
*
* @throws \Exception
* @return void
* @return int
*/
public function mockery_teardown()
public function mockery_allocateOrder()
{
try {
$this->mockery_verify();
} catch (\Exception $e) {
$this->mockery_close();
throw $e;
}
}
/**
* Verify the container mocks
*
* @return void
*/
public function mockery_verify()
{
foreach ($this->_mocks as $mock) {
$mock->mockery_verify();
}
}
/**
* Retrieves all exceptions thrown by mocks
*
* @return array
*/
public function mockery_thrownExceptions()
{
$e = [];
foreach ($this->_mocks as $mock) {
$e = array_merge($e, $mock->mockery_thrownExceptions());
}
return $e;
return ++$this->_allocatedOrder;
}
/**
@@ -326,51 +444,8 @@ class Container
foreach ($this->_mocks as $mock) {
$mock->mockery_teardown();
}
$this->_mocks = array();
}
/**
* Fetch the next available allocation order number
*
* @return int
*/
public function mockery_allocateOrder()
{
$this->_allocatedOrder += 1;
return $this->_allocatedOrder;
}
/**
* Set ordering for a group
*
* @param mixed $group
* @param int $order
*/
public function mockery_setGroup($group, $order)
{
$this->_groups[$group] = $order;
}
/**
* Fetch array of ordered groups
*
* @return array
*/
public function mockery_getGroups()
{
return $this->_groups;
}
/**
* Set current ordered number
*
* @param int $order
* @return int The current order number that was set
*/
public function mockery_setCurrentOrder($order)
{
$this->_currentOrder = $order;
return $this->_currentOrder;
$this->_mocks = [];
}
/**
@@ -383,30 +458,6 @@ class Container
return $this->_currentOrder;
}
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
* @throws \Mockery\Exception
* @return void
*/
public function mockery_validateOrder($method, $order, \Mockery\LegacyMockInterface $mock)
{
if ($order < $this->_currentOrder) {
$exception = new \Mockery\Exception\InvalidOrderException(
'Method ' . $method . ' called out of order: expected order '
. $order . ', was ' . $this->_currentOrder
);
$exception->setMock($mock)
->setMethodName($method)
->setExpectedOrder($order)
->setActualOrder($this->_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
/**
* Gets the count of expectations on the mocks
*
@@ -418,36 +469,151 @@ class Container
foreach ($this->_mocks as $mock) {
$count += $mock->mockery_getExpectationCount();
}
return $count;
}
/**
* Fetch array of ordered groups
*
* @return array<string,int>
*/
public function mockery_getGroups()
{
return $this->_groups;
}
/**
* Set current ordered number
*
* @param int $order
*
* @return int The current order number that was set
*/
public function mockery_setCurrentOrder($order)
{
return $this->_currentOrder = $order;
}
/**
* Set ordering for a group
*
* @param string $group
* @param int $order
*
* @return void
*/
public function mockery_setGroup($group, $order)
{
$this->_groups[$group] = $order;
}
/**
* Tear down tasks for this container
*
* @throws PHPException
*/
public function mockery_teardown()
{
try {
$this->mockery_verify();
} catch (PHPException $phpException) {
$this->mockery_close();
throw $phpException;
}
}
/**
* Retrieves all exceptions thrown by mocks
*
* @return array<Throwable>
*/
public function mockery_thrownExceptions()
{
/** @var array<Throwable> $exceptions */
$exceptions = [];
foreach ($this->_mocks as $mock) {
foreach ($mock->mockery_thrownExceptions() as $exception) {
$exceptions[] = $exception;
}
}
return $exceptions;
}
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
*
* @throws Exception
*/
public function mockery_validateOrder($method, $order, LegacyMockInterface $mock)
{
if ($order < $this->_currentOrder) {
$exception = new InvalidOrderException(
sprintf(
'Method %s called out of order: expected order %d, was %d',
$method,
$order,
$this->_currentOrder
)
);
$exception->setMock($mock)
->setMethodName($method)
->setExpectedOrder($order)
->setActualOrder($this->_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
/**
* Verify the container mocks
*/
public function mockery_verify()
{
foreach ($this->_mocks as $mock) {
$mock->mockery_verify();
}
}
/**
* Store a mock and set its container reference
*
* @param \Mockery\Mock $mock
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
* @template TRememberMock of object
*
* @param LegacyMockInterface&MockInterface&TRememberMock $mock
*
* @return LegacyMockInterface&MockInterface&TRememberMock
*/
public function rememberMock(\Mockery\LegacyMockInterface $mock)
public function rememberMock(LegacyMockInterface $mock)
{
if (!isset($this->_mocks[get_class($mock)])) {
$this->_mocks[get_class($mock)] = $mock;
} else {
/**
* This condition triggers for an instance mock where origin mock
* is already remembered
*/
$this->_mocks[] = $mock;
$class = get_class($mock);
if (! array_key_exists($class, $this->_mocks)) {
return $this->_mocks[$class] = $mock;
}
return $mock;
/**
* This condition triggers for an instance mock where origin mock
* is already remembered
*/
return $this->_mocks[] = $mock;
}
/**
* Retrieve the last remembered mock object, which is the same as saying
* retrieve the current mock being programmed where you have yet to call
* mock() to change it - thus why the method name is "self" since it will be
* be used during the programming of the same mock.
* Retrieve the last remembered mock object,
* which is the same as saying retrieve the current mock being programmed where you have yet to call mock()
* to change it thus why the method name is "self" since it will be used during the programming of the same mock.
*
* @return \Mockery\Mock
* @return LegacyMockInterface|MockInterface
*/
public function self()
{
@@ -457,35 +623,32 @@ class Container
}
/**
* Return a specific remembered mock according to the array index it
* was stored to in this container instance
* @template TMock of object
* @template TMixed
*
* @return \Mockery\Mock
* @param class-string<TMock> $mockName
* @param null|array<TMixed> $constructorArgs
*
* @return TMock
*/
public function fetchMock($reference)
{
if (isset($this->_mocks[$reference])) {
return $this->_mocks[$reference];
}
}
protected function _getInstance($mockName, $constructorArgs = null)
{
if ($constructorArgs !== null) {
$r = new \ReflectionClass($mockName);
return $r->newInstanceArgs($constructorArgs);
return (new ReflectionClass($mockName))->newInstanceArgs($constructorArgs);
}
try {
$instantiator = new Instantiator();
$instance = $instantiator->instantiate($mockName);
} catch (\Exception $ex) {
$instance = $this->instantiator->instantiate($mockName);
} catch (PHPException $phpException) {
/** @var class-string<TMock> $internalMockName */
$internalMockName = $mockName . '_Internal';
if (!class_exists($internalMockName)) {
eval("class $internalMockName extends $mockName {" .
'public function __construct() {}' .
'}');
if (! class_exists($internalMockName)) {
eval(sprintf(
'class %s extends %s { public function __construct() {} }',
$internalMockName,
$mockName
));
}
$instance = new $internalMockName();
@@ -498,38 +661,18 @@ class Container
{
$name = $config->getName();
if (!$name) {
if ($name === null) {
return;
}
$hash = $config->getHash();
if (isset($this->_namedMocks[$name])) {
if ($hash !== $this->_namedMocks[$name]) {
throw new \Mockery\Exception(
"The mock named '$name' has been already defined with a different mock configuration"
);
}
if (array_key_exists($name, $this->_namedMocks) && $hash !== $this->_namedMocks[$name]) {
throw new Exception(
sprintf("The mock named '%s' has been already defined with a different mock configuration", $name)
);
}
$this->_namedMocks[$name] = $hash;
}
/**
* see http://php.net/manual/en/language.oop5.basic.php
* @param string $className
* @return bool
*/
public function isValidClassName($className)
{
$pos = strpos($className, '\\');
if ($pos === 0) {
$className = substr($className, 1); // remove the first backslash
}
// all the namespaces and class name should match the regex
$invalidNames = array_filter(explode('\\', $className), function ($name) {
return !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
});
return empty($invalidNames);
}
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\CountValidator;
use Mockery;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class AtLeast extends CountValidatorAbstract
{
@@ -28,6 +20,7 @@ class AtLeast extends CountValidatorAbstract
* Checks if the validator can accept an additional nth call
*
* @param int $n
*
* @return bool
*/
public function isEligible($n)
@@ -39,18 +32,21 @@ class AtLeast extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
{
if ($this->_limit > $n) {
$exception = new Mockery\Exception\InvalidCountException(
$exception = new InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL
. ' at least ' . $this->_limit . ' times but called ' . $n
. ' times.'
);
$exception->setMock($this->_expectation->getMock())
->setMethodName((string) $this->_expectation)
->setExpectedCountComparative('>=')

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\CountValidator;
use Mockery;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class AtMost extends CountValidatorAbstract
{
@@ -28,12 +20,14 @@ class AtMost extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
{
if ($this->_limit < $n) {
$exception = new Mockery\Exception\InvalidCountException(
$exception = new InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL

View File

@@ -1,31 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\CountValidator;
abstract class CountValidatorAbstract
use Mockery\Expectation;
abstract class CountValidatorAbstract implements CountValidatorInterface
{
/**
* Expectation for which this validator is assigned
*
* @var \Mockery\Expectation
* @var Expectation
*/
protected $_expectation = null;
@@ -39,10 +31,9 @@ abstract class CountValidatorAbstract
/**
* Set Expectation object and upper call limit
*
* @param \Mockery\Expectation $expectation
* @param int $limit
*/
public function __construct(\Mockery\Expectation $expectation, $limit)
public function __construct(Expectation $expectation, $limit)
{
$this->_expectation = $expectation;
$this->_limit = $limit;
@@ -52,17 +43,19 @@ abstract class CountValidatorAbstract
* Checks if the validator can accept an additional nth call
*
* @param int $n
*
* @return bool
*/
public function isEligible($n)
{
return ($n < $this->_limit);
return $n < $this->_limit;
}
/**
* Validate the call count against this validator
*
* @param int $n
*
* @return bool
*/
abstract public function validate($n);

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\CountValidator;
use Mockery;
use Mockery\Exception\InvalidCountException;
use const PHP_EOL;
class Exact extends CountValidatorAbstract
{
@@ -28,6 +20,8 @@ class Exact extends CountValidatorAbstract
* Validate the call count against this validator
*
* @param int $n
*
* @throws InvalidCountException
* @return bool
*/
public function validate($n)
@@ -35,7 +29,7 @@ class Exact extends CountValidatorAbstract
if ($this->_limit !== $n) {
$because = $this->_expectation->getExceptionMessage();
$exception = new Mockery\Exception\InvalidCountException(
$exception = new InvalidCountException(
'Method ' . (string) $this->_expectation
. ' from ' . $this->_expectation->getMock()->mockery_getName()
. ' should be called' . PHP_EOL

View File

@@ -1,25 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\CountValidator;
class Exception extends \OutOfBoundsException
use Mockery\Exception\MockeryExceptionInterface;
use OutOfBoundsException;
class Exception extends OutOfBoundsException implements MockeryExceptionInterface
{
}

View File

@@ -1,25 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class Exception extends \UnexpectedValueException
use Mockery\Exception\MockeryExceptionInterface;
use UnexpectedValueException;
class Exception extends UnexpectedValueException implements MockeryExceptionInterface
{
}

View File

@@ -1,21 +1,37 @@
<?php
/**
* Mockery (https://docs.mockery.io/)
*
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
class BadMethodCallException extends \BadMethodCallException
class BadMethodCallException extends \BadMethodCallException implements MockeryExceptionInterface
{
/**
* @var bool
*/
private $dismissed = false;
public function dismiss()
{
$this->dismissed = true;
// we sometimes stack them
if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) {
$this->getPrevious()->dismiss();
$previous = $this->getPrevious();
if (! $previous instanceof self) {
return;
}
$previous->dismiss();
}
/**
* @return bool
*/
public function dismissed()
{
return $this->dismissed;

View File

@@ -1,25 +1,15 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
class InvalidArgumentException extends \InvalidArgumentException
class InvalidArgumentException extends \InvalidArgumentException implements MockeryExceptionInterface
{
}

View File

@@ -1,102 +1,152 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
use Mockery;
use Mockery\Exception\RuntimeException;
use Mockery\CountValidator\Exception;
use Mockery\LegacyMockInterface;
class InvalidCountException extends Mockery\CountValidator\Exception
use function in_array;
class InvalidCountException extends Exception
{
protected $method = null;
protected $expected = 0;
protected $expectedComparative = '<=';
/**
* @var int|null
*/
protected $actual = null;
/**
* @var int
*/
protected $expected = 0;
/**
* @var string
*/
protected $expectedComparative = '<=';
/**
* @var string|null
*/
protected $method = null;
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return int|null
*/
public function getActualCount()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return int
*/
public function getExpectedCount()
{
$this->method = $name;
return $this;
return $this->expected;
}
/**
* @return string
*/
public function getExpectedCountComparative()
{
return $this->expectedComparative;
}
/**
* @return string|null
*/
public function getMethodName()
{
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @throws RuntimeException
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return '';
}
return $mock->mockery_getName();
}
/**
* @param int $count
* @return self
*/
public function setActualCount($count)
{
$this->actual = $count;
return $this;
}
/**
* @param int $count
* @return self
*/
public function setExpectedCount($count)
{
$this->expected = $count;
return $this;
}
/**
* @param string $comp
* @return self
*/
public function setExpectedCountComparative($comp)
{
if (!in_array($comp, array('=', '>', '<', '>=', '<='))) {
throw new RuntimeException(
'Illegal comparative for expected call counts set: ' . $comp
);
if (! in_array($comp, ['=', '>', '<', '>=', '<='], true)) {
throw new RuntimeException('Illegal comparative for expected call counts set: ' . $comp);
}
$this->expectedComparative = $comp;
return $this;
}
public function getMock()
/**
* @param string $name
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
return $this->method;
}
public function getActualCount()
{
return $this->actual;
}
public function getExpectedCount()
{
return $this->expected;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
}
public function getExpectedCountComparative()
{
return $this->expectedComparative;
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,83 +1,125 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
use Mockery;
use Mockery\Exception;
use Mockery\LegacyMockInterface;
class InvalidOrderException extends Mockery\Exception
class InvalidOrderException extends Exception
{
protected $method = null;
protected $expected = 0;
/**
* @var int|null
*/
protected $actual = null;
/**
* @var int
*/
protected $expected = 0;
/**
* @var string|null
*/
protected $method = null;
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return int|null
*/
public function getActualOrder()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return int
*/
public function getExpectedOrder()
{
$this->method = $name;
return $this;
return $this->expected;
}
/**
* @return string|null
*/
public function getMethodName()
{
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return $mock;
}
return $mock->mockery_getName();
}
/**
* @param int $count
*
* @return self
*/
public function setActualOrder($count)
{
$this->actual = $count;
return $this;
}
/**
* @param int $count
*
* @return self
*/
public function setExpectedOrder($count)
{
$this->expected = $count;
return $this;
}
public function getMock()
/**
* @param string $name
*
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
return $this->method;
}
public function getActualOrder()
{
return $this->actual;
}
public function getExpectedOrder()
{
return $this->expected;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,70 +1,102 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
use Mockery;
use Mockery\Exception;
use Mockery\LegacyMockInterface;
class NoMatchingExpectationException extends Mockery\Exception
class NoMatchingExpectationException extends Exception
{
/**
* @var array<mixed>
*/
protected $actual = [];
/**
* @var string|null
*/
protected $method = null;
protected $actual = array();
/**
* @var LegacyMockInterface|null
*/
protected $mockObject = null;
public function setMock(Mockery\LegacyMockInterface $mock)
/**
* @return array<mixed>
*/
public function getActualArguments()
{
$this->mockObject = $mock;
return $this;
return $this->actual;
}
public function setMethodName($name)
/**
* @return string|null
*/
public function getMethodName()
{
$this->method = $name;
return $this;
return $this->method;
}
/**
* @return LegacyMockInterface|null
*/
public function getMock()
{
return $this->mockObject;
}
/**
* @return string|null
*/
public function getMockName()
{
$mock = $this->getMock();
if ($mock === null) {
return $mock;
}
return $mock->mockery_getName();
}
/**
* @todo Rename param `count` to `args`
* @template TMixed
*
* @param array<TMixed> $count
* @return self
*/
public function setActualArguments($count)
{
$this->actual = $count;
return $this;
}
public function getMock()
/**
* @param string $name
* @return self
*/
public function setMethodName($name)
{
return $this->mockObject;
$this->method = $name;
return $this;
}
public function getMethodName()
/**
* @return self
*/
public function setMock(LegacyMockInterface $mock)
{
return $this->method;
}
public function getActualArguments()
{
return $this->actual;
}
public function getMockName()
{
return $this->getMock()->mockery_getName();
$this->mockObject = $mock;
return $this;
}
}

View File

@@ -1,25 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Exception;
class RuntimeException extends \Exception
use Exception;
class RuntimeException extends Exception implements MockeryExceptionInterface
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Mockery;
use Mockery\Exception\NoMatchingExpectationException;
use function array_pop;
use function array_unshift;
use function end;
use const PHP_EOL;
class ExpectationDirector
{
/**
* Method name the director is directing
* Stores an array of all default expectations for this mock
*
* @var string
* @var list<ExpectationInterface>
*/
protected $_name = null;
/**
* Mock object the director is attached to
*
* @var \Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
protected $_mock = null;
protected $_defaults = [];
/**
* Stores an array of all expectations for this mock
*
* @var array
* @var list<ExpectationInterface>
*/
protected $_expectations = array();
protected $_expectations = [];
/**
* The expected order of next call
@@ -51,19 +43,25 @@ class ExpectationDirector
protected $_expectedOrder = null;
/**
* Stores an array of all default expectations for this mock
* Mock object the director is attached to
*
* @var array
* @var LegacyMockInterface|MockInterface
*/
protected $_defaults = array();
protected $_mock = null;
/**
* Method name the director is directing
*
* @var string
*/
protected $_name = null;
/**
* Constructor
*
* @param string $name
* @param \Mockery\LegacyMockInterface $mock
*/
public function __construct($name, \Mockery\LegacyMockInterface $mock)
public function __construct($name, LegacyMockInterface $mock)
{
$this->_name = $name;
$this->_mock = $mock;
@@ -71,10 +69,8 @@ class ExpectationDirector
/**
* Add a new expectation to the director
*
* @param \Mockery\Expectation $expectation
*/
public function addExpectation(\Mockery\Expectation $expectation)
public function addExpectation(Expectation $expectation)
{
$this->_expectations[] = $expectation;
}
@@ -82,124 +78,56 @@ class ExpectationDirector
/**
* Handle a method call being directed by this instance
*
* @param array $args
* @return mixed
*/
public function call(array $args)
{
$expectation = $this->findExpectation($args);
if (is_null($expectation)) {
$exception = new \Mockery\Exception\NoMatchingExpectationException(
'No matching handler found for '
. $this->_mock->mockery_getName() . '::'
. \Mockery::formatArgs($this->_name, $args)
. '. Either the method was unexpected or its arguments matched'
. ' no expected argument list for this method'
. PHP_EOL . PHP_EOL
. \Mockery::formatObjects($args)
);
$exception->setMock($this->_mock)
->setMethodName($this->_name)
->setActualArguments($args);
throw $exception;
if ($expectation !== null) {
return $expectation->verifyCall($args);
}
return $expectation->verifyCall($args);
}
/**
* Verify all expectations of the director
*
* @throws \Mockery\CountValidator\Exception
* @return void
*/
public function verify()
{
if (!empty($this->_expectations)) {
foreach ($this->_expectations as $exp) {
$exp->verify();
}
} else {
foreach ($this->_defaults as $exp) {
$exp->verify();
}
}
$exception = new NoMatchingExpectationException(
'No matching handler found for '
. $this->_mock->mockery_getName() . '::'
. Mockery::formatArgs($this->_name, $args)
. '. Either the method was unexpected or its arguments matched'
. ' no expected argument list for this method'
. PHP_EOL . PHP_EOL
. Mockery::formatObjects($args)
);
$exception->setMock($this->_mock)
->setMethodName($this->_name)
->setActualArguments($args);
throw $exception;
}
/**
* Attempt to locate an expectation matching the provided args
*
* @param array $args
* @return mixed
*/
public function findExpectation(array $args)
{
$expectation = null;
if (!empty($this->_expectations)) {
if ($this->_expectations !== []) {
$expectation = $this->_findExpectationIn($this->_expectations, $args);
}
if ($expectation === null && !empty($this->_defaults)) {
$expectation = $this->_findExpectationIn($this->_defaults, $args);
if ($expectation === null && $this->_defaults !== []) {
return $this->_findExpectationIn($this->_defaults, $args);
}
return $expectation;
}
/**
* Make the given expectation a default for all others assuming it was
* correctly created last
*
* @param \Mockery\Expectation $expectation
*/
public function makeExpectationDefault(\Mockery\Expectation $expectation)
{
$last = end($this->_expectations);
if ($last === $expectation) {
array_pop($this->_expectations);
array_unshift($this->_defaults, $expectation);
} else {
throw new \Mockery\Exception(
'Cannot turn a previously defined expectation into a default'
);
}
}
/**
* Search current array of expectations for a match
*
* @param array $expectations
* @param array $args
* @return mixed
*/
protected function _findExpectationIn(array $expectations, array $args)
{
foreach ($expectations as $exp) {
if ($exp->isEligible() && $exp->matchArgs($args)) {
return $exp;
}
}
foreach ($expectations as $exp) {
if ($exp->matchArgs($args)) {
return $exp;
}
}
}
/**
* Return all expectations assigned to this director
*
* @return array
*/
public function getExpectations()
{
return $this->_expectations;
}
/**
* Return all expectations assigned to this director
*
* @return array
* @return array<ExpectationInterface>
*/
public function getDefaultExpectations()
{
@@ -213,6 +141,102 @@ class ExpectationDirector
*/
public function getExpectationCount()
{
return count($this->getExpectations()) ?: count($this->getDefaultExpectations());
$count = 0;
$expectations = $this->getExpectations();
if ($expectations === []) {
$expectations = $this->getDefaultExpectations();
}
foreach ($expectations as $expectation) {
if ($expectation->isCallCountConstrained()) {
++$count;
}
}
return $count;
}
/**
* Return all expectations assigned to this director
*
* @return array<ExpectationInterface>
*/
public function getExpectations()
{
return $this->_expectations;
}
/**
* Make the given expectation a default for all others assuming it was correctly created last
*
* @throws Exception
*
* @return void
*/
public function makeExpectationDefault(Expectation $expectation)
{
if (end($this->_expectations) === $expectation) {
array_pop($this->_expectations);
array_unshift($this->_defaults, $expectation);
return;
}
throw new Exception('Cannot turn a previously defined expectation into a default');
}
/**
* Verify all expectations of the director
*
* @throws Exception
*
* @return void
*/
public function verify()
{
if ($this->_expectations !== []) {
foreach ($this->_expectations as $expectation) {
$expectation->verify();
}
return;
}
foreach ($this->_defaults as $expectation) {
$expectation->verify();
}
}
/**
* Search current array of expectations for a match
*
* @param array<ExpectationInterface> $expectations
*
* @return null|ExpectationInterface
*/
protected function _findExpectationIn(array $expectations, array $args)
{
foreach ($expectations as $expectation) {
if (! $expectation->isEligible()) {
continue;
}
if (! $expectation->matchArgs($args)) {
continue;
}
return $expectation;
}
foreach ($expectations as $expectation) {
if ($expectation->matchArgs($args)) {
return $expectation;
}
}
return null;
}
}

View File

@@ -1,22 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
@@ -24,17 +13,10 @@ namespace Mockery;
interface ExpectationInterface
{
/**
* @return int
*/
public function getOrderNumber();
/**
* @return LegacyMockInterface|MockInterface
*/
public function getMock();
/**
* @param mixed $args
* @template TArgs
*
* @param TArgs ...$args
*
* @return self
*/
public function andReturn(...$args);
@@ -43,4 +25,14 @@ interface ExpectationInterface
* @return self
*/
public function andReturns();
/**
* @return LegacyMockInterface|MockInterface
*/
public function getMock();
/**
* @return int
*/
public function getOrderNumber();
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
@@ -24,10 +14,14 @@ class ExpectsHigherOrderMessage extends HigherOrderMessage
{
public function __construct(MockInterface $mock)
{
parent::__construct($mock, "shouldReceive");
parent::__construct($mock, 'shouldReceive');
}
/**
* @return \Mockery\Expectation
* @param string $method
* @param array $args
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function __call($method, $args)
{

View File

@@ -1,45 +1,43 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
class CachingGenerator implements Generator
{
/**
* @var array<string,string>
*/
protected $cache = [];
/**
* @var Generator
*/
protected $generator;
protected $cache = array();
public function __construct(Generator $generator)
{
$this->generator = $generator;
}
/**
* @return string
*/
public function generate(MockConfiguration $config)
{
$hash = $config->getHash();
if (isset($this->cache[$hash])) {
if (array_key_exists($hash, $this->cache)) {
return $this->cache[$hash];
}
$definition = $this->generator->generate($config);
$this->cache[$hash] = $definition;
return $definition;
return $this->cache[$hash] = $this->generator->generate($config);
}
}

View File

@@ -1,96 +1,140 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionMethod;
use function array_map;
use function array_merge;
use function array_unique;
use const PHP_VERSION_ID;
class DefinedTargetClass implements TargetClassInterface
{
private $rfc;
/**
* @var class-string
*/
private $name;
public function __construct(\ReflectionClass $rfc, $alias = null)
/**
* @var ReflectionClass
*/
private $rfc;
/**
* @param ReflectionClass $rfc
* @param class-string|null $alias
*/
public function __construct(ReflectionClass $rfc, $alias = null)
{
$this->rfc = $rfc;
$this->name = $alias === null ? $rfc->getName() : $alias;
$this->name = $alias ?? $rfc->getName();
}
/**
* @return class-string
*/
public function __toString()
{
return $this->name;
}
/**
* @param class-string $name
* @param class-string|null $alias
* @return self
*/
public static function factory($name, $alias = null)
{
return new self(new \ReflectionClass($name), $alias);
return new self(new ReflectionClass($name), $alias);
}
/**
* @return list<class-string>
*/
public function getAttributes()
{
if (PHP_VERSION_ID < 80000) {
return [];
}
return array_unique(
array_merge(
['\AllowDynamicProperties'],
array_map(
static function (ReflectionAttribute $attribute): string {
return '\\' . $attribute->getName();
},
$this->rfc->getAttributes()
)
)
);
}
/**
* @return array<class-string,self>
*/
public function getInterfaces()
{
return array_map(
static function (ReflectionClass $interface): self {
return new self($interface);
},
$this->rfc->getInterfaces()
);
}
/**
* @return list<Method>
*/
public function getMethods()
{
return array_map(
static function (ReflectionMethod $method): Method {
return new Method($method);
},
$this->rfc->getMethods()
);
}
/**
* @return class-string
*/
public function getName()
{
return $this->name;
}
public function isAbstract()
{
return $this->rfc->isAbstract();
}
public function isFinal()
{
return $this->rfc->isFinal();
}
public function getMethods()
{
return array_map(function ($method) {
return new Method($method);
}, $this->rfc->getMethods());
}
public function getInterfaces()
{
$class = __CLASS__;
return array_map(function ($interface) use ($class) {
return new $class($interface);
}, $this->rfc->getInterfaces());
}
public function __toString()
{
return $this->getName();
}
/**
* @return string
*/
public function getNamespaceName()
{
return $this->rfc->getNamespaceName();
}
public function inNamespace()
{
return $this->rfc->inNamespace();
}
/**
* @return string
*/
public function getShortName()
{
return $this->rfc->getShortName();
}
public function implementsInterface($interface)
{
return $this->rfc->implementsInterface($interface);
}
/**
* @return bool
*/
public function hasInternalAncestor()
{
if ($this->rfc->isInternal()) {
@@ -102,9 +146,43 @@ class DefinedTargetClass implements TargetClassInterface
if ($parent->isInternal()) {
return true;
}
$child = $parent;
}
return false;
}
/**
* @param class-string $interface
* @return bool
*/
public function implementsInterface($interface)
{
return $this->rfc->implementsInterface($interface);
}
/**
* @return bool
*/
public function inNamespace()
{
return $this->rfc->inNamespace();
}
/**
* @return bool
*/
public function isAbstract()
{
return $this->rfc->isAbstract();
}
/**
* @return bool
*/
public function isFinal()
{
return $this->rfc->isFinal();
}
}

View File

@@ -1,27 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
interface Generator
{
/** @returns MockDefinition */
/**
* @returns MockDefinition
*/
public function generate(MockConfiguration $config);
}

View File

@@ -1,54 +1,63 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use Mockery\Reflector;
use ReflectionMethod;
use ReflectionParameter;
use function array_map;
/**
* @mixin ReflectionMethod
*/
class Method
{
/** @var \ReflectionMethod */
/**
* @var ReflectionMethod
*/
private $method;
public function __construct(\ReflectionMethod $method)
public function __construct(ReflectionMethod $method)
{
$this->method = $method;
}
/**
* @template TArgs
* @template TMixed
*
* @param string $method
* @param array<TArgs> $args
*
* @return TMixed
*/
public function __call($method, $args)
{
return call_user_func_array(array($this->method, $method), $args);
/** @var TMixed */
return $this->method->{$method}(...$args);
}
/**
* @return Parameter[]
* @return list<Parameter>
*/
public function getParameters()
{
return array_map(function (\ReflectionParameter $parameter) {
return array_map(static function (ReflectionParameter $parameter) {
return new Parameter($parameter);
}, $this->method->getParameters());
}
/**
* @return string|null
* @return null|string
*/
public function getReturnType()
{

View File

@@ -1,25 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use Mockery\Exception;
use Serializable;
use function array_filter;
use function array_keys;
use function array_map;
use function array_merge;
use function array_pop;
use function array_unique;
use function array_values;
use function class_alias;
use function class_exists;
use function explode;
use function get_class;
use function implode;
use function in_array;
use function interface_exists;
use function is_object;
use function md5;
use function preg_match;
use function serialize;
use function strpos;
use function strtolower;
use function trait_exists;
/**
* This class describes the configuration of mocks and hides away some of the
* reflection implementation
@@ -27,80 +41,117 @@ namespace Mockery\Generator;
class MockConfiguration
{
/**
* A class that we'd like to mock
* Instance cache of all methods
*
* @var list<Method>
*/
protected $targetClass;
protected $targetClassName;
/**
* A number of interfaces we'd like to mock, keyed by name to attempt to
* keep unique
*/
protected $targetInterfaces = array();
protected $targetInterfaceNames = array();
/**
* A number of traits we'd like to mock, keyed by name to attempt to
* keep unique
*/
protected $targetTraits = array();
protected $targetTraitNames = array();
/**
* An object we'd like our mock to proxy to
*/
protected $targetObject;
/**
* The class name we'd like to use for a generated mock
*/
protected $name;
protected $allMethods = [];
/**
* Methods that should specifically not be mocked
*
* This is currently populated with stuff we don't know how to deal with,
* should really be somewhere else
* This is currently populated with stuff we don't know how to deal with, should really be somewhere else
*/
protected $blackListedMethods = array();
protected $blackListedMethods = [];
protected $constantsMap = [];
/**
* If not empty, only these methods will be mocked
*/
protected $whiteListedMethods = array();
/**
* An instance mock is where we override the original class before it's
* autoloaded
* An instance mock is where we override the original class before it's autoloaded
*
* @var bool
*/
protected $instanceMock = false;
/**
* Param overrides
*/
protected $parameterOverrides = array();
/**
* Instance cache of all methods
*/
protected $allMethods;
/**
* If true, overrides original class destructor
*
* @var bool
*/
protected $mockOriginalDestructor = false;
protected $constantsMap = array();
/**
* The class name we'd like to use for a generated mock
*
* @var string|null
*/
protected $name;
/**
* Param overrides
*
* @var array<string,mixed>
*/
protected $parameterOverrides = [];
/**
* A class that we'd like to mock
* @var TargetClassInterface|null
*/
protected $targetClass;
/**
* @var class-string|null
*/
protected $targetClassName;
/**
* @var array<class-string>
*/
protected $targetInterfaceNames = [];
/**
* A number of interfaces we'd like to mock, keyed by name to attempt to keep unique
*
* @var array<TargetClassInterface>
*/
protected $targetInterfaces = [];
/**
* An object we'd like our mock to proxy to
*
* @var object|null
*/
protected $targetObject;
/**
* @var array<string>
*/
protected $targetTraitNames = [];
/**
* A number of traits we'd like to mock, keyed by name to attempt to keep unique
*
* @var array<string,DefinedTargetClass>
*/
protected $targetTraits = [];
/**
* If not empty, only these methods will be mocked
*
* @var array<string>
*/
protected $whiteListedMethods = [];
/**
* @param array<class-string|object> $targets
* @param array<string> $blackListedMethods
* @param array<string> $whiteListedMethods
* @param string|null $name
* @param bool $instanceMock
* @param array<string,mixed> $parameterOverrides
* @param bool $mockOriginalDestructor
* @param array<string,array<scalar>|scalar> $constantsMap
*/
public function __construct(
array $targets = array(),
array $blackListedMethods = array(),
array $whiteListedMethods = array(),
array $targets = [],
array $blackListedMethods = [],
array $whiteListedMethods = [],
$name = null,
$instanceMock = false,
array $parameterOverrides = array(),
array $parameterOverrides = [],
$mockOriginalDestructor = false,
array $constantsMap = array()
array $constantsMap = []
) {
$this->addTargets($targets);
$this->blackListedMethods = $blackListedMethods;
@@ -112,6 +163,52 @@ class MockConfiguration
$this->constantsMap = $constantsMap;
}
/**
* Generate a suitable name based on the config
*
* @return string
*/
public function generateName()
{
$nameBuilder = new MockNameBuilder();
$targetObject = $this->getTargetObject();
if ($targetObject !== null) {
$className = get_class($targetObject);
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
$targetClass = $this->getTargetClass();
if ($targetClass instanceof TargetClassInterface) {
$className = $targetClass->getName();
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
foreach ($this->getTargetInterfaces() as $targetInterface) {
$nameBuilder->addPart($targetInterface->getName());
}
return $nameBuilder->build();
}
/**
* @return array<string>
*/
public function getBlackListedMethods()
{
return $this->blackListedMethods;
}
/**
* @return array<string,scalar|array<scalar>>
*/
public function getConstantsMap()
{
return $this->constantsMap;
}
/**
* Attempt to create a hash of the configuration, in order to allow caching
*
@@ -121,25 +218,26 @@ class MockConfiguration
*/
public function getHash()
{
$vars = array(
'targetClassName' => $this->targetClassName,
'targetInterfaceNames' => $this->targetInterfaceNames,
'targetTraitNames' => $this->targetTraitNames,
'name' => $this->name,
'blackListedMethods' => $this->blackListedMethods,
'whiteListedMethod' => $this->whiteListedMethods,
'instanceMock' => $this->instanceMock,
'parameterOverrides' => $this->parameterOverrides,
'mockOriginalDestructor' => $this->mockOriginalDestructor
);
$vars = [
'targetClassName' => $this->targetClassName,
'targetInterfaceNames' => $this->targetInterfaceNames,
'targetTraitNames' => $this->targetTraitNames,
'name' => $this->name,
'blackListedMethods' => $this->blackListedMethods,
'whiteListedMethod' => $this->whiteListedMethods,
'instanceMock' => $this->instanceMock,
'parameterOverrides' => $this->parameterOverrides,
'mockOriginalDestructor' => $this->mockOriginalDestructor,
];
return md5(serialize($vars));
}
/**
* Gets a list of methods from the classes, interfaces and objects and
* filters them appropriately. Lot's of filtering going on, perhaps we could
* have filter classes to iterate through
* Gets a list of methods from the classes, interfaces and objects and filters them appropriately.
* Lot's of filtering going on, perhaps we could have filter classes to iterate through
*
* @return list<Method>
*/
public function getMethodsToMock()
{
@@ -154,22 +252,28 @@ class MockConfiguration
/**
* Whitelist trumps everything else
*/
if (count($this->getWhiteListedMethods())) {
$whitelist = array_map('strtolower', $this->getWhiteListedMethods());
$methods = array_filter($methods, function ($method) use ($whitelist) {
return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist);
});
$whiteListedMethods = $this->getWhiteListedMethods();
if ($whiteListedMethods !== []) {
$whitelist = array_map('strtolower', $whiteListedMethods);
return $methods;
return array_filter($methods, static function ($method) use ($whitelist) {
if ($method->isAbstract()) {
return true;
}
return in_array(strtolower($method->getName()), $whitelist, true);
});
}
/**
* Remove blacklisted methods
*/
if (count($this->getBlackListedMethods())) {
$blacklist = array_map('strtolower', $this->getBlackListedMethods());
$methods = array_filter($methods, function ($method) use ($blacklist) {
return !in_array(strtolower($method->getName()), $blacklist);
$blackListedMethods = $this->getBlackListedMethods();
if ($blackListedMethods !== []) {
$blacklist = array_map('strtolower', $blackListedMethods);
$methods = array_filter($methods, static function ($method) use ($blacklist) {
return ! in_array(strtolower($method->getName()), $blacklist, true);
});
}
@@ -179,11 +283,15 @@ class MockConfiguration
* such, we can't mock it and will need a pass to add a dummy
* implementation
*/
if ($this->getTargetClass()
&& $this->getTargetClass()->implementsInterface("Serializable")
&& $this->getTargetClass()->hasInternalAncestor()) {
$methods = array_filter($methods, function ($method) {
return $method->getName() !== "unserialize";
$targetClass = $this->getTargetClass();
if (
$targetClass !== null
&& $targetClass->implementsInterface(Serializable::class)
&& $targetClass->hasInternalAncestor()
) {
$methods = array_filter($methods, static function ($method) {
return $method->getName() !== 'unserialize';
});
}
@@ -191,40 +299,213 @@ class MockConfiguration
}
/**
* We declare the __call method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
* @return string|null
*/
public function requiresCallTypeHintRemoval()
public function getName()
{
foreach ($this->getAllMethods() as $method) {
if ("__call" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
}
}
return false;
return $this->name;
}
/**
* We declare the __callStatic method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
* @return string
*/
public function requiresCallStaticTypeHintRemoval()
public function getNamespaceName()
{
foreach ($this->getAllMethods() as $method) {
if ("__callStatic" === $method->getName()) {
$params = $method->getParameters();
return !$params[1]->isArray();
$parts = explode('\\', $this->getName());
array_pop($parts);
if ($parts !== []) {
return implode('\\', $parts);
}
return '';
}
/**
* @return array<string,mixed>
*/
public function getParameterOverrides()
{
return $this->parameterOverrides;
}
/**
* @return string
*/
public function getShortName()
{
$parts = explode('\\', $this->getName());
return array_pop($parts);
}
/**
* @return null|TargetClassInterface
*/
public function getTargetClass()
{
if ($this->targetClass) {
return $this->targetClass;
}
if (! $this->targetClassName) {
return null;
}
if (class_exists($this->targetClassName)) {
$alias = null;
if (strpos($this->targetClassName, '@') !== false) {
$alias = (new MockNameBuilder())
->addPart('anonymous_class')
->addPart(md5($this->targetClassName))
->build();
class_alias($this->targetClassName, $alias);
}
$dtc = DefinedTargetClass::factory($this->targetClassName, $alias);
if ($this->getTargetObject() === null && $dtc->isFinal()) {
throw new Exception(
'The class ' . $this->targetClassName . ' is marked final and its methods'
. ' cannot be replaced. Classes marked final can be passed in'
. ' to \Mockery::mock() as instantiated objects to create a'
. ' partial mock, but only if the mock is not subject to type'
. ' hinting checks.'
);
}
$this->targetClass = $dtc;
} else {
$this->targetClass = UndefinedTargetClass::factory($this->targetClassName);
}
return $this->targetClass;
}
/**
* @return class-string|null
*/
public function getTargetClassName()
{
return $this->targetClassName;
}
/**
* @return list<TargetClassInterface>
*/
public function getTargetInterfaces()
{
if ($this->targetInterfaces !== []) {
return $this->targetInterfaces;
}
foreach ($this->targetInterfaceNames as $targetInterface) {
if (! interface_exists($targetInterface)) {
$this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface);
continue;
}
$dtc = DefinedTargetClass::factory($targetInterface);
$extendedInterfaces = array_keys($dtc->getInterfaces());
$extendedInterfaces[] = $targetInterface;
$traversableFound = false;
$iteratorShiftedToFront = false;
foreach ($extendedInterfaces as $interface) {
if (! $traversableFound && preg_match('/^\\?Iterator(|Aggregate)$/i', $interface)) {
break;
}
if (preg_match('/^\\\\?IteratorAggregate$/i', $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory('\\IteratorAggregate');
$iteratorShiftedToFront = true;
continue;
}
if (preg_match('/^\\\\?Iterator$/i', $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory('\\Iterator');
$iteratorShiftedToFront = true;
continue;
}
if (preg_match('/^\\\\?Traversable$/i', $interface)) {
$traversableFound = true;
}
}
if ($traversableFound && ! $iteratorShiftedToFront) {
$this->targetInterfaces[] = DefinedTargetClass::factory('\\IteratorAggregate');
}
/**
* We never straight up implement Traversable
*/
$isTraversable = preg_match('/^\\\\?Traversable$/i', $targetInterface);
if ($isTraversable === 0 || $isTraversable === false) {
$this->targetInterfaces[] = $dtc;
}
}
return false;
return $this->targetInterfaces = array_unique($this->targetInterfaces);
}
/**
* @return object|null
*/
public function getTargetObject()
{
return $this->targetObject;
}
/**
* @return list<TargetClassInterface>
*/
public function getTargetTraits()
{
if ($this->targetTraits !== []) {
return $this->targetTraits;
}
foreach ($this->targetTraitNames as $targetTrait) {
$this->targetTraits[] = DefinedTargetClass::factory($targetTrait);
}
$this->targetTraits = array_unique($this->targetTraits); // just in case
return $this->targetTraits;
}
/**
* @return array<string>
*/
public function getWhiteListedMethods()
{
return $this->whiteListedMethods;
}
/**
* @return bool
*/
public function isInstanceMock()
{
return $this->instanceMock;
}
/**
* @return bool
*/
public function isMockOriginalDestructor()
{
return $this->mockOriginalDestructor;
}
/**
* @param class-string $className
* @return self
*/
public function rename($className)
{
$targets = array();
$targets = [];
if ($this->targetClassName) {
$targets[] = $this->targetClassName;
@@ -254,31 +535,75 @@ class MockConfiguration
);
}
/**
* We declare the __callStatic method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
*
* @return bool
*/
public function requiresCallStaticTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ($method->getName() === '__callStatic') {
$params = $method->getParameters();
if (! array_key_exists(1, $params)) {
return false;
}
return ! $params[1]->isArray();
}
}
return false;
}
/**
* We declare the __call method to handle undefined stuff, if the class
* we're mocking has also defined it, we need to comply with their interface
*
* @return bool
*/
public function requiresCallTypeHintRemoval()
{
foreach ($this->getAllMethods() as $method) {
if ($method->getName() === '__call') {
$params = $method->getParameters();
return ! $params[1]->isArray();
}
}
return false;
}
/**
* @param class-string|object $target
*/
protected function addTarget($target)
{
if (is_object($target)) {
$this->setTargetObject($target);
$this->setTargetClassName(get_class($target));
return $this;
return;
}
if ($target[0] !== "\\") {
$target = "\\" . $target;
if ($target[0] !== '\\') {
$target = '\\' . $target;
}
if (class_exists($target)) {
$this->setTargetClassName($target);
return $this;
return;
}
if (interface_exists($target)) {
$this->addTargetInterfaceName($target);
return $this;
return;
}
if (trait_exists($target)) {
$this->addTargetTraitName($target);
return $this;
return;
}
/**
@@ -289,12 +614,27 @@ class MockConfiguration
*/
if ($this->getTargetClassName()) {
$this->addTargetInterfaceName($target);
return $this;
return;
}
$this->setTargetClassName($target);
}
/**
* If we attempt to implement Traversable,
* we must ensure we are also implementing either Iterator or IteratorAggregate,
* and that whichever one it is comes before Traversable in the list of implements.
*
* @param class-string $targetInterface
*/
protected function addTargetInterfaceName($targetInterface)
{
$this->targetInterfaceNames[] = $targetInterface;
}
/**
* @param array<class-string> $interfaces
*/
protected function addTargets($interfaces)
{
foreach ($interfaces as $interface) {
@@ -302,195 +642,17 @@ class MockConfiguration
}
}
public function getTargetClassName()
/**
* @param class-string $targetTraitName
*/
protected function addTargetTraitName($targetTraitName)
{
return $this->targetClassName;
}
public function getTargetClass()
{
if ($this->targetClass) {
return $this->targetClass;
}
if (!$this->targetClassName) {
return null;
}
if (class_exists($this->targetClassName)) {
$alias = null;
if (strpos($this->targetClassName, '@') !== false) {
$alias = (new MockNameBuilder())
->addPart('anonymous_class')
->addPart(md5($this->targetClassName))
->build();
class_alias($this->targetClassName, $alias);
}
$dtc = DefinedTargetClass::factory($this->targetClassName, $alias);
if ($this->getTargetObject() == false && $dtc->isFinal()) {
throw new \Mockery\Exception(
'The class ' . $this->targetClassName . ' is marked final and its methods'
. ' cannot be replaced. Classes marked final can be passed in'
. ' to \Mockery::mock() as instantiated objects to create a'
. ' partial mock, but only if the mock is not subject to type'
. ' hinting checks.'
);
}
$this->targetClass = $dtc;
} else {
$this->targetClass = UndefinedTargetClass::factory($this->targetClassName);
}
return $this->targetClass;
}
public function getTargetTraits()
{
if (!empty($this->targetTraits)) {
return $this->targetTraits;
}
foreach ($this->targetTraitNames as $targetTrait) {
$this->targetTraits[] = DefinedTargetClass::factory($targetTrait);
}
$this->targetTraits = array_unique($this->targetTraits); // just in case
return $this->targetTraits;
}
public function getTargetInterfaces()
{
if (!empty($this->targetInterfaces)) {
return $this->targetInterfaces;
}
foreach ($this->targetInterfaceNames as $targetInterface) {
if (!interface_exists($targetInterface)) {
$this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface);
continue;
}
$dtc = DefinedTargetClass::factory($targetInterface);
$extendedInterfaces = array_keys($dtc->getInterfaces());
$extendedInterfaces[] = $targetInterface;
$traversableFound = false;
$iteratorShiftedToFront = false;
foreach ($extendedInterfaces as $interface) {
if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) {
break;
}
if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
$iteratorShiftedToFront = true;
} elseif (preg_match("/^\\\\?Iterator$/i", $interface)) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator");
$iteratorShiftedToFront = true;
} elseif (preg_match("/^\\\\?Traversable$/i", $interface)) {
$traversableFound = true;
}
}
if ($traversableFound && !$iteratorShiftedToFront) {
$this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
}
/**
* We never straight up implement Traversable
*/
if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) {
$this->targetInterfaces[] = $dtc;
}
}
$this->targetInterfaces = array_unique($this->targetInterfaces); // just in case
return $this->targetInterfaces;
}
public function getTargetObject()
{
return $this->targetObject;
}
public function getName()
{
return $this->name;
$this->targetTraitNames[] = $targetTraitName;
}
/**
* Generate a suitable name based on the config
* @return list<Method>
*/
public function generateName()
{
$nameBuilder = new MockNameBuilder();
if ($this->getTargetObject()) {
$className = get_class($this->getTargetObject());
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
if ($this->getTargetClass()) {
$className = $this->getTargetClass()->getName();
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
}
foreach ($this->getTargetInterfaces() as $targetInterface) {
$nameBuilder->addPart($targetInterface->getName());
}
return $nameBuilder->build();
}
public function getShortName()
{
$parts = explode("\\", $this->getName());
return array_pop($parts);
}
public function getNamespaceName()
{
$parts = explode("\\", $this->getName());
array_pop($parts);
if (count($parts)) {
return implode("\\", $parts);
}
return "";
}
public function getBlackListedMethods()
{
return $this->blackListedMethods;
}
public function getWhiteListedMethods()
{
return $this->whiteListedMethods;
}
public function isInstanceMock()
{
return $this->instanceMock;
}
public function getParameterOverrides()
{
return $this->parameterOverrides;
}
public function isMockOriginalDestructor()
{
return $this->mockOriginalDestructor;
}
protected function setTargetClassName($targetClassName)
{
$this->targetClassName = $targetClassName;
}
protected function getAllMethods()
{
if ($this->allMethods) {
@@ -503,7 +665,7 @@ class MockConfiguration
$classes[] = $this->getTargetClass();
}
$methods = array();
$methods = [];
foreach ($classes as $class) {
$methods = array_merge($methods, $class->getMethods());
}
@@ -516,9 +678,9 @@ class MockConfiguration
}
}
$names = array();
$methods = array_filter($methods, function ($method) use (&$names) {
if (in_array($method->getName(), $names)) {
$names = [];
$methods = array_filter($methods, static function ($method) use (&$names) {
if (in_array($method->getName(), $names, true)) {
return false;
}
@@ -530,27 +692,18 @@ class MockConfiguration
}
/**
* If we attempt to implement Traversable, we must ensure we are also
* implementing either Iterator or IteratorAggregate, and that whichever one
* it is comes before Traversable in the list of implements.
* @param class-string $targetClassName
*/
protected function addTargetInterfaceName($targetInterface)
protected function setTargetClassName($targetClassName)
{
$this->targetInterfaceNames[] = $targetInterface;
}
protected function addTargetTraitName($targetTraitName)
{
$this->targetTraitNames[] = $targetTraitName;
$this->targetClassName = $targetClassName;
}
/**
* @param object $object
*/
protected function setTargetObject($object)
{
$this->targetObject = $object;
}
public function getConstantsMap()
{
return $this->constantsMap;
}
}

View File

@@ -1,29 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use function array_diff;
class MockConfigurationBuilder
{
protected $name;
protected $blackListedMethods = array(
/**
* @var list<string>
*/
protected $blackListedMethods = [
'__call',
'__callStatic',
'__clone',
@@ -36,45 +30,101 @@ class MockConfigurationBuilder
'__debugInfo', ## mocking this makes it difficult to debug with xdebug
// below are reserved words in PHP
"__halt_compiler", "abstract", "and", "array", "as",
"break", "callable", "case", "catch", "class",
"clone", "const", "continue", "declare", "default",
"die", "do", "echo", "else", "elseif",
"empty", "enddeclare", "endfor", "endforeach", "endif",
"endswitch", "endwhile", "eval", "exit", "extends",
"final", "for", "foreach", "function", "global",
"goto", "if", "implements", "include", "include_once",
"instanceof", "insteadof", "interface", "isset", "list",
"namespace", "new", "or", "print", "private",
"protected", "public", "require", "require_once", "return",
"static", "switch", "throw", "trait", "try",
"unset", "use", "var", "while", "xor"
);
protected $php7SemiReservedKeywords = [
"callable", "class", "trait", "extends", "implements", "static", "abstract", "final",
"public", "protected", "private", "const", "enddeclare", "endfor", "endforeach", "endif",
"endwhile", "and", "global", "goto", "instanceof", "insteadof", "interface", "namespace", "new",
"or", "xor", "try", "use", "var", "exit", "list", "clone", "include", "include_once", "throw",
"array", "print", "echo", "require", "require_once", "return", "else", "elseif", "default",
"break", "continue", "switch", "yield", "function", "if", "endswitch", "finally", "for", "foreach",
"declare", "case", "do", "while", "as", "catch", "die", "self", "parent",
'__halt_compiler', 'abstract', 'and', 'array', 'as',
'break', 'callable', 'case', 'catch', 'class',
'clone', 'const', 'continue', 'declare', 'default',
'die', 'do', 'echo', 'else', 'elseif',
'empty', 'enddeclare', 'endfor', 'endforeach', 'endif',
'endswitch', 'endwhile', 'eval', 'exit', 'extends',
'final', 'for', 'foreach', 'function', 'global',
'goto', 'if', 'implements', 'include', 'include_once',
'instanceof', 'insteadof', 'interface', 'isset', 'list',
'namespace', 'new', 'or', 'print', 'private',
'protected', 'public', 'require', 'require_once', 'return',
'static', 'switch', 'throw', 'trait', 'try',
'unset', 'use', 'var', 'while', 'xor',
];
protected $whiteListedMethods = array();
/**
* @var array
*/
protected $constantsMap = [];
/**
* @var bool
*/
protected $instanceMock = false;
protected $parameterOverrides = array();
/**
* @var bool
*/
protected $mockOriginalDestructor = false;
protected $targets = array();
protected $constantsMap = array();
/**
* @var string
*/
protected $name;
/**
* @var array
*/
protected $parameterOverrides = [];
/**
* @var list<string>
*/
protected $php7SemiReservedKeywords = [
'callable', 'class', 'trait', 'extends', 'implements', 'static', 'abstract', 'final',
'public', 'protected', 'private', 'const', 'enddeclare', 'endfor', 'endforeach', 'endif',
'endwhile', 'and', 'global', 'goto', 'instanceof', 'insteadof', 'interface', 'namespace', 'new',
'or', 'xor', 'try', 'use', 'var', 'exit', 'list', 'clone', 'include', 'include_once', 'throw',
'array', 'print', 'echo', 'require', 'require_once', 'return', 'else', 'elseif', 'default',
'break', 'continue', 'switch', 'yield', 'function', 'if', 'endswitch', 'finally', 'for', 'foreach',
'declare', 'case', 'do', 'while', 'as', 'catch', 'die', 'self', 'parent',
];
/**
* @var array
*/
protected $targets = [];
/**
* @var array
*/
protected $whiteListedMethods = [];
public function __construct()
{
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
}
/**
* @param string $blackListedMethod
* @return self
*/
public function addBlackListedMethod($blackListedMethod)
{
$this->blackListedMethods[] = $blackListedMethod;
return $this;
}
/**
* @param list<string> $blackListedMethods
* @return self
*/
public function addBlackListedMethods(array $blackListedMethods)
{
foreach ($blackListedMethods as $method) {
$this->addBlackListedMethod($method);
}
return $this;
}
/**
* @param class-string $target
* @return self
*/
public function addTarget($target)
{
$this->targets[] = $target;
@@ -82,6 +132,10 @@ class MockConfigurationBuilder
return $this;
}
/**
* @param list<class-string> $targets
* @return self
*/
public function addTargets($targets)
{
foreach ($targets as $target) {
@@ -91,73 +145,30 @@ class MockConfigurationBuilder
return $this;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function addBlackListedMethod($blackListedMethod)
{
$this->blackListedMethods[] = $blackListedMethod;
return $this;
}
public function addBlackListedMethods(array $blackListedMethods)
{
foreach ($blackListedMethods as $method) {
$this->addBlackListedMethod($method);
}
return $this;
}
public function setBlackListedMethods(array $blackListedMethods)
{
$this->blackListedMethods = $blackListedMethods;
return $this;
}
/**
* @return self
*/
public function addWhiteListedMethod($whiteListedMethod)
{
$this->whiteListedMethods[] = $whiteListedMethod;
return $this;
}
/**
* @return self
*/
public function addWhiteListedMethods(array $whiteListedMethods)
{
foreach ($whiteListedMethods as $method) {
$this->addWhiteListedMethod($method);
}
return $this;
}
public function setWhiteListedMethods(array $whiteListedMethods)
{
$this->whiteListedMethods = $whiteListedMethods;
return $this;
}
public function setInstanceMock($instanceMock)
{
$this->instanceMock = (bool) $instanceMock;
}
public function setParameterOverrides(array $overrides)
{
$this->parameterOverrides = $overrides;
}
public function setMockOriginalDestructor($mockDestructor)
{
$this->mockOriginalDestructor = $mockDestructor;
return $this;
}
public function setConstantsMap(array $map)
{
$this->constantsMap = $map;
}
/**
* @return MockConfiguration
*/
public function getMockConfiguration()
{
return new MockConfiguration(
@@ -171,4 +182,71 @@ class MockConfigurationBuilder
$this->constantsMap
);
}
/**
* @param list<string> $blackListedMethods
* @return self
*/
public function setBlackListedMethods(array $blackListedMethods)
{
$this->blackListedMethods = $blackListedMethods;
return $this;
}
/**
* @return self
*/
public function setConstantsMap(array $map)
{
$this->constantsMap = $map;
return $this;
}
/**
* @param bool $instanceMock
*/
public function setInstanceMock($instanceMock)
{
$this->instanceMock = (bool) $instanceMock;
return $this;
}
/**
* @param bool $mockDestructor
*/
public function setMockOriginalDestructor($mockDestructor)
{
$this->mockOriginalDestructor = (bool) $mockDestructor;
return $this;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return self
*/
public function setParameterOverrides(array $overrides)
{
$this->parameterOverrides = $overrides;
return $this;
}
/**
* @param list<string> $whiteListedMethods
* @return self
*/
public function setWhiteListedMethods(array $whiteListedMethods)
{
$this->whiteListedMethods = $whiteListedMethods;
return $this;
}
}

View File

@@ -1,51 +1,64 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use InvalidArgumentException;
class MockDefinition
{
protected $config;
/**
* @var string
*/
protected $code;
/**
* @var MockConfiguration
*/
protected $config;
/**
* @param string $code
* @throws InvalidArgumentException
*/
public function __construct(MockConfiguration $config, $code)
{
if (!$config->getName()) {
throw new \InvalidArgumentException("MockConfiguration must contain a name");
if (! $config->getName()) {
throw new InvalidArgumentException('MockConfiguration must contain a name');
}
$this->config = $config;
$this->code = $code;
}
public function getConfig()
{
return $this->config;
}
/**
* @return string
*/
public function getClassName()
{
return $this->config->getName();
}
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @return MockConfiguration
*/
public function getConfig()
{
return $this->config;
}
}

View File

@@ -1,31 +1,33 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use function implode;
use function str_replace;
class MockNameBuilder
{
/**
* @var int
*/
protected static $mockCounter = 0;
/**
* @var list<string>
*/
protected $parts = [];
/**
* @param string $part
*/
public function addPart($part)
{
$this->parts[] = $part;
@@ -33,12 +35,15 @@ class MockNameBuilder
return $this;
}
/**
* @return string
*/
public function build()
{
$parts = ['Mockery', static::$mockCounter++];
foreach ($this->parts as $part) {
$parts[] = str_replace("\\", "_", $part);
$parts[] = str_replace('\\', '_', $part);
}
return implode('_', $parts);

View File

@@ -1,43 +1,55 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use Mockery\Reflector;
use ReflectionClass;
use ReflectionParameter;
use function class_exists;
/**
* @mixin ReflectionParameter
*/
class Parameter
{
/** @var int */
/**
* @var int
*/
private static $parameterCounter = 0;
/** @var \ReflectionParameter */
/**
* @var ReflectionParameter
*/
private $rfp;
public function __construct(\ReflectionParameter $rfp)
public function __construct(ReflectionParameter $rfp)
{
$this->rfp = $rfp;
}
/**
* Proxy all method calls to the reflection parameter.
*
* @template TMixed
* @template TResult
*
* @param string $method
* @param array<TMixed> $args
*
* @return TResult
*/
public function __call($method, array $args)
{
return call_user_func_array(array($this->rfp, $method), $args);
/** @var TResult */
return $this->rfp->{$method}(...$args);
}
/**
@@ -45,7 +57,7 @@ class Parameter
*
* This will be null if there was no type, or it was a scalar or a union.
*
* @return \ReflectionClass|null
* @return null|ReflectionClass
*
* @deprecated since 1.3.3 and will be removed in 2.0.
*/
@@ -53,13 +65,31 @@ class Parameter
{
$typeHint = Reflector::getTypeHint($this->rfp, true);
return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
return class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
}
/**
* Get the name of the parameter.
*
* Some internal classes have funny looking definitions!
*
* @return string
*/
public function getName()
{
$name = $this->rfp->getName();
if (! $name || $name === '...') {
return 'arg' . self::$parameterCounter++;
}
return $name;
}
/**
* Get the string representation for the paramater type.
*
* @return string|null
* @return null|string
*/
public function getTypeHint()
{
@@ -78,23 +108,6 @@ class Parameter
return (string) Reflector::getTypeHint($this->rfp, true);
}
/**
* Get the name of the parameter.
*
* Some internal classes have funny looking definitions!
*
* @return string
*/
public function getName()
{
$name = $this->rfp->getName();
if (!$name || $name == '...') {
$name = 'arg' . self::$parameterCounter++;
}
return $name;
}
/**
* Determine if the parameter is an array.
*

View File

@@ -1,46 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\Method;
use Mockery\Generator\Parameter;
use Mockery\Generator\MockConfiguration;
use function array_map;
use function in_array;
use function preg_replace;
use function sprintf;
use function str_replace;
class AvoidMethodClashPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$names = array_map(function ($method) {
$names = array_map(static function ($method) {
return $method->getName();
}, $config->getMethodsToMock());
foreach (["allows", "expects"] as $method) {
if (in_array($method, $names)) {
$code = preg_replace(
"#// start method {$method}.*// end method {$method}#ms",
"",
$code
);
foreach (['allows', 'expects'] as $method) {
if (in_array($method, $names, true)) {
$code = preg_replace(sprintf('#// start method %s.*// end method %s#ms', $method, $method), '', $code);
$code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code);
$code = str_replace(' implements MockInterface', ' implements LegacyMockInterface', $code);
}
}

View File

@@ -1,29 +1,24 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function str_replace;
class CallTypeHintPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
if ($config->requiresCallTypeHintRemoval()) {
@@ -35,7 +30,7 @@ class CallTypeHintPass implements Pass
}
if ($config->requiresCallStaticTypeHintRemoval()) {
$code = str_replace(
return str_replace(
'public static function __callStatic($method, array $args)',
'public static function __callStatic($method, $args)',
$code

View File

@@ -1,49 +1,35 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function ltrim;
use function str_replace;
class ClassNamePass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$namespace = $config->getNamespaceName();
$namespace = ltrim($namespace, "\\");
$namespace = ltrim($namespace, '\\');
$className = $config->getShortName();
$code = str_replace(
'namespace Mockery;',
$namespace ? 'namespace ' . $namespace . ';' : '',
$code
);
$code = str_replace('namespace Mockery;', $namespace !== '' ? 'namespace ' . $namespace . ';' : '', $code);
$code = str_replace(
'class Mock',
'class ' . $className,
$code
);
return $code;
return str_replace('class Mock', 'class ' . $className, $code);
}
}

View File

@@ -1,34 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery;
use Mockery\Generator\MockConfiguration;
use function class_exists;
use function ltrim;
use function str_replace;
class ClassPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
@@ -36,18 +34,16 @@ class ClassPass implements Pass
return $code;
}
$className = ltrim($target->getName(), "\\");
$className = ltrim($target->getName(), '\\');
if (!class_exists($className)) {
\Mockery::declareClass($className);
if (! class_exists($className)) {
Mockery::declareClass($className);
}
$code = str_replace(
"implements MockInterface",
"extends \\" . $className . " implements MockInterface",
return str_replace(
'implements MockInterface',
'extends \\' . $className . ' implements MockInterface',
$code
);
return $code;
}
}

View File

@@ -1,33 +1,51 @@
<?php
/**
* Mockery (https://docs.mockery.io/)
*
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function array_key_exists;
use function sprintf;
use function strrpos;
use function substr_replace;
use function var_export;
use const PHP_EOL;
class ConstantsPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$cm = $config->getConstantsMap();
if (empty($cm)) {
if ($cm === []) {
return $code;
}
if (!isset($cm[$config->getName()])) {
$name = $config->getName();
if (! array_key_exists($name, $cm)) {
return $code;
}
$cm = $cm[$config->getName()];
$constantsCode = '';
foreach ($cm as $constant => $value) {
foreach ($cm[$name] as $constant => $value) {
$constantsCode .= sprintf("\n const %s = %s;\n", $constant, var_export($value, true));
}
$i = strrpos($code, '}');
$code = substr_replace($code, $constantsCode, $i);
$code .= "}\n";
$offset = strrpos($code, '}');
if ($offset === false) {
return $code;
}
return $code;
return substr_replace($code, $constantsCode, $offset) . '}' . PHP_EOL;
}
}

View File

@@ -1,30 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function strrpos;
use function substr;
class InstanceMockPass
class InstanceMockPass implements Pass
{
const INSTANCE_MOCK_CODE = <<<MOCK
public const INSTANCE_MOCK_CODE = <<<MOCK
protected \$_mockery_ignoreVerification = true;
@@ -60,15 +52,19 @@ class InstanceMockPass
}
}
\Mockery::getContainer()->rememberMock(\$this);
\$this->_mockery_constructorCalled(func_get_args());
}
MOCK;
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
if ($config->isInstanceMock()) {
$code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
return $this->appendToClass($code, static::INSTANCE_MOCK_CODE);
}
return $code;
@@ -76,8 +72,7 @@ MOCK;
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
}

View File

@@ -1,48 +1,41 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery;
use Mockery\Generator\MockConfiguration;
use function array_reduce;
use function interface_exists;
use function ltrim;
use function str_replace;
class InterfacePass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
foreach ($config->getTargetInterfaces() as $i) {
$name = ltrim($i->getName(), "\\");
if (!interface_exists($name)) {
\Mockery::declareInterface($name);
$name = ltrim($i->getName(), '\\');
if (! interface_exists($name)) {
Mockery::declareInterface($name);
}
}
$interfaces = array_reduce((array) $config->getTargetInterfaces(), function ($code, $i) {
return $code . ", \\" . ltrim($i->getName(), "\\");
}, "");
$interfaces = array_reduce($config->getTargetInterfaces(), static function ($code, $i) {
return $code . ', \\' . ltrim($i->getName(), '\\');
}, '');
$code = str_replace(
"implements MockInterface",
"implements MockInterface" . $interfaces,
$code
);
return $code;
return str_replace('implements MockInterface', 'implements MockInterface' . $interfaces, $code);
}
}

View File

@@ -1,36 +1,36 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\TargetClassInterface;
use Mockery\Generator\Method;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\Parameter;
use Mockery\Generator\TargetClassInterface;
use function array_filter;
use function array_merge;
use function end;
use function in_array;
use function is_array;
use function preg_match;
use function preg_match_all;
use function preg_replace;
use function rtrim;
use function sprintf;
class MagicMethodTypeHintsPass implements Pass
{
/**
* @var array $mockMagicMethods
* @var array
*/
private $mockMagicMethods = array(
private $mockMagicMethods = [
'__construct',
'__destruct',
'__call',
@@ -45,14 +45,14 @@ class MagicMethodTypeHintsPass implements Pass
'__invoke',
'__set_state',
'__clone',
'__debugInfo'
);
'__debugInfo',
];
/**
* Apply implementation.
*
* @param string $code
* @param MockConfiguration $config
*
* @return string
*/
public function apply($code, MockConfiguration $config)
@@ -73,113 +73,81 @@ class MagicMethodTypeHintsPass implements Pass
* Returns the magic methods within the
* passed DefinedTargetClass.
*
* @param TargetClassInterface $class
* @return array
*/
public function getMagicMethods(
TargetClassInterface $class = null
) {
if (is_null($class)) {
return array();
public function getMagicMethods(?TargetClassInterface $class = null)
{
if (! $class instanceof TargetClassInterface) {
return [];
}
return array_filter($class->getMethods(), function (Method $method) {
return in_array($method->getName(), $this->mockMagicMethods);
return in_array($method->getName(), $this->mockMagicMethods, true);
});
}
protected function renderTypeHint(Parameter $param)
{
$typeHint = $param->getTypeHint();
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
}
/**
* Applies type hints of magic methods from
* class to the passed code.
*
* @param int $code
* @param Method $method
*
* @return string
*/
private function applyMagicTypeHints($code, Method $method)
{
if ($this->isMethodWithinCode($code, $method)) {
$namedParameters = $this->getOriginalParameters(
$code,
$method
);
$namedParameters = $this->getOriginalParameters($code, $method);
$code = preg_replace(
$this->getDeclarationRegex($method->getName()),
$this->getMethodDeclaration($method, $namedParameters),
$code
);
}
return $code;
}
/**
* Checks if the method is declared within code.
* Returns a regex string used to match the
* declaration of some method.
*
* @param int $code
* @param Method $method
* @return boolean
*/
private function isMethodWithinCode($code, Method $method)
{
return preg_match(
$this->getDeclarationRegex($method->getName()),
$code
) == 1;
}
/**
* Returns the method original parameters, as they're
* described in the $code string.
* @param string $methodName
*
* @param int $code
* @param Method $method
* @return array
* @return string
*/
private function getOriginalParameters($code, Method $method)
private function getDeclarationRegex($methodName)
{
$matches = [];
$parameterMatches = [];
preg_match(
$this->getDeclarationRegex($method->getName()),
$code,
$matches
);
if (count($matches) > 0) {
preg_match_all(
'/(?<=\$)(\w+)+/i',
$matches[0],
$parameterMatches
);
}
$groupMatches = end($parameterMatches);
$parameterNames = is_array($groupMatches) ? $groupMatches : [$groupMatches];
return $parameterNames;
return sprintf('/public\s+(?:static\s+)?function\s+%s\s*\(.*\)\s*(?=\{)/i', $methodName);
}
/**
* Gets the declaration code, as a string, for the passed method.
*
* @param Method $method
* @param array $namedParameters
* @param array $namedParameters
*
* @return string
*/
private function getMethodDeclaration(
Method $method,
array $namedParameters
) {
private function getMethodDeclaration(Method $method, array $namedParameters)
{
$declaration = 'public';
$declaration .= $method->isStatic() ? ' static' : '';
$declaration .= ' function ' . $method->getName() . '(';
foreach ($method->getParameters() as $index => $parameter) {
$declaration .= $this->renderTypeHint($parameter);
$name = isset($namedParameters[$index]) ? $namedParameters[$index] : $parameter->getName();
$name = $namedParameters[$index] ?? $parameter->getName();
$declaration .= '$' . $name;
$declaration .= ',';
}
$declaration = rtrim($declaration, ',');
$declaration .= ') ';
@@ -191,22 +159,39 @@ class MagicMethodTypeHintsPass implements Pass
return $declaration;
}
protected function renderTypeHint(Parameter $param)
/**
* Returns the method original parameters, as they're
* described in the $code string.
*
* @param int $code
*
* @return array
*/
private function getOriginalParameters($code, Method $method)
{
$typeHint = $param->getTypeHint();
$matches = [];
$parameterMatches = [];
return $typeHint === null ? '' : sprintf('%s ', $typeHint);
preg_match($this->getDeclarationRegex($method->getName()), $code, $matches);
if ($matches !== []) {
preg_match_all('/(?<=\$)(\w+)+/i', $matches[0], $parameterMatches);
}
$groupMatches = end($parameterMatches);
return is_array($groupMatches) ? $groupMatches : [$groupMatches];
}
/**
* Returns a regex string used to match the
* declaration of some method.
* Checks if the method is declared within code.
*
* @param string $methodName
* @return string
* @param int $code
*
* @return bool
*/
private function getDeclarationRegex($methodName)
private function isMethodWithinCode($code, Method $method)
{
return "/public\s+(?:static\s+)?function\s+$methodName\s*\(.*\)\s*(?=\{)/i";
return preg_match($this->getDeclarationRegex($method->getName()), $code) === 1;
}
}

View File

@@ -1,31 +1,40 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\Method;
use Mockery\Generator\Parameter;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\Parameter;
use function array_values;
use function count;
use function enum_exists;
use function get_class;
use function implode;
use function in_array;
use function is_object;
use function preg_match;
use function sprintf;
use function strpos;
use function strrpos;
use function strtolower;
use function substr;
use function var_export;
use const PHP_VERSION_ID;
class MethodDefinitionPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
foreach ($config->getMethodsToMock() as $method) {
@@ -54,6 +63,12 @@ class MethodDefinitionPass implements Pass
return $code;
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
protected function renderParams(Method $method, $config)
{
$class = $method->getDeclaringClass();
@@ -65,18 +80,41 @@ class MethodDefinitionPass implements Pass
}
}
$methodParams = array();
$methodParams = [];
$params = $method->getParameters();
$isPhp81 = PHP_VERSION_ID >= 80100;
foreach ($params as $param) {
$paramDef = $this->renderTypeHint($param);
$paramDef .= $param->isPassedByReference() ? '&' : '';
$paramDef .= $param->isVariadic() ? '...' : '';
$paramDef .= '$' . $param->getName();
if (!$param->isVariadic()) {
if (false !== $param->isDefaultValueAvailable()) {
if (! $param->isVariadic()) {
if ($param->isDefaultValueAvailable() !== false) {
$defaultValue = $param->getDefaultValue();
$paramDef .= ' = ' . (is_object($defaultValue) ? get_class($defaultValue) : var_export($defaultValue, true));
if (is_object($defaultValue)) {
$prefix = get_class($defaultValue);
if ($isPhp81) {
if (enum_exists($prefix)) {
$prefix = var_export($defaultValue, true);
} elseif (
! $param->isDefaultValueConstant() &&
// "Parameter #1 [ <optional> F\Q\CN $a = new \F\Q\CN(param1, param2: 2) ]
preg_match(
'#<optional>\s.*?\s=\snew\s(.*?)\s]$#',
$param->__toString(),
$matches
) === 1
) {
$prefix = 'new ' . $matches[1];
}
}
} else {
$prefix = var_export($defaultValue, true);
}
$paramDef .= ' = ' . $prefix;
} elseif ($param->isOptional()) {
$paramDef .= ' = null';
}
@@ -84,6 +122,7 @@ class MethodDefinitionPass implements Pass
$methodParams[] = $paramDef;
}
return '(' . implode(', ', $methodParams) . ')';
}
@@ -94,13 +133,6 @@ class MethodDefinitionPass implements Pass
return $type ? sprintf(': %s', $type) : '';
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
}
protected function renderTypeHint(Parameter $param)
{
$typeHint = $param->getTypeHint();
@@ -131,8 +163,8 @@ BODY;
$param = $params[$i];
if (strpos($param, '&') !== false) {
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] = {$param};
if (\$argc > {$i}) {
\$argv[{$i}] = {$param};
}
BODY;
@@ -143,12 +175,13 @@ BODY;
$paramCount = count($params);
for ($i = 0; $i < $paramCount; ++$i) {
$param = $params[$i];
if (!$param->isPassedByReference()) {
if (! $param->isPassedByReference()) {
continue;
}
$body .= <<<BODY
if (\$argc > $i) {
\$argv[$i] =& \${$param->getName()};
if (\$argc > {$i}) {
\$argv[{$i}] =& \${$param->getName()};
}
BODY;
@@ -157,11 +190,10 @@ BODY;
$body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n";
if ($method->getReturnType() !== "void") {
if (! in_array($method->getReturnType(), ['never', 'void'], true)) {
$body .= "return \$ret;\n";
}
$body .= "}\n";
return $body;
return $body . "}\n";
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
@@ -24,5 +14,9 @@ use Mockery\Generator\MockConfiguration;
interface Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config);
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use Mockery\Generator\TargetClassInterface;
use function preg_replace;
/**
* The standard Mockery\Mock class includes some methods to ease mocking, such
@@ -28,24 +20,35 @@ use Mockery\Generator\MockConfiguration;
* mocked. This pass removes the builtin methods where they are final on the
* target
*/
class RemoveBuiltinMethodsThatAreFinalPass
class RemoveBuiltinMethodsThatAreFinalPass implements Pass
{
protected $methods = array(
protected $methods = [
'__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm',
);
'__toString' => '/public function __toString\(\)\s+(:\s+string)?\s*\{.*?\}/sm',
];
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target instanceof TargetClassInterface) {
return $code;
}
foreach ($target->getMethods() as $method) {
if ($method->isFinal() && isset($this->methods[$method->getName()])) {
$code = preg_replace($this->methods[$method->getName()], '', $code);
if (! $method->isFinal()) {
continue;
}
if (! isset($this->methods[$method->getName()])) {
continue;
}
$code = preg_replace($this->methods[$method->getName()], '', $code);
}
return $code;

View File

@@ -1,43 +1,37 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @author Boris Avdeev <elephant@lislon.ru>
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function preg_replace;
/**
* Remove mock's empty destructor if we tend to use original class destructor
*/
class RemoveDestructorPass
class RemoveDestructorPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
if (!$config->isMockOriginalDestructor()) {
$code = preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code);
if (! $config->isMockOriginalDestructor()) {
return preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code);
}
return $code;

View File

@@ -1,26 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function strrpos;
use function substr;
use const PHP_VERSION_ID;
/**
* Internal classes can not be instantiated with the newInstanceWithoutArgs
@@ -28,32 +21,37 @@ use Mockery\Generator\MockConfiguration;
* implements Serializable, we need to replace the standard unserialize method
* definition with a dummy
*/
class RemoveUnserializeForInternalSerializableClassesPass
class RemoveUnserializeForInternalSerializableClassesPass implements Pass
{
const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} ';
const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} ';
public const DUMMY_METHOD_DEFINITION = 'public function unserialize(string $data): void {} ';
public const DUMMY_METHOD_DEFINITION_LEGACY = 'public function unserialize($string) {} ';
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$target = $config->getTargetClass();
if (!$target) {
if (! $target) {
return $code;
}
if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) {
if (! $target->hasInternalAncestor() || ! $target->implementsInterface('Serializable')) {
return $code;
}
$code = $this->appendToClass($code, \PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION);
return $code;
return $this->appendToClass(
$code,
PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION
);
}
protected function appendToClass($class, $code)
{
$lastBrace = strrpos($class, "}");
$class = substr($class, 0, $lastBrace) . $code . "\n }\n";
return $class;
$lastBrace = strrpos($class, '}');
return substr($class, 0, $lastBrace) . $code . "\n }\n";
}
}

View File

@@ -1,47 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator\StringManipulation\Pass;
use Mockery\Generator\MockConfiguration;
use function array_map;
use function implode;
use function ltrim;
use function preg_replace;
class TraitPass implements Pass
{
/**
* @param string $code
* @return string
*/
public function apply($code, MockConfiguration $config)
{
$traits = $config->getTargetTraits();
if (empty($traits)) {
if ($traits === []) {
return $code;
}
$useStatements = array_map(function ($trait) {
return "use \\\\" . ltrim($trait->getName(), "\\") . ";";
$useStatements = array_map(static function ($trait) {
return 'use \\\\' . ltrim($trait->getName(), '\\') . ';';
}, $traits);
$code = preg_replace(
'/^{$/m',
"{\n " . implode("\n ", $useStatements) . "\n",
$code
);
return $code;
return preg_replace('/^{$/m', "{\n " . implode("\n ", $useStatements) . "\n", $code);
}
}

View File

@@ -1,26 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use Mockery\Generator\StringManipulation\Pass\AvoidMethodClashPass;
use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
use Mockery\Generator\StringManipulation\Pass\ClassAttributesPass;
use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
use Mockery\Generator\StringManipulation\Pass\ClassPass;
use Mockery\Generator\StringManipulation\Pass\ConstantsPass;
@@ -33,11 +25,55 @@ use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPa
use Mockery\Generator\StringManipulation\Pass\RemoveDestructorPass;
use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass;
use Mockery\Generator\StringManipulation\Pass\TraitPass;
use Mockery\Generator\StringManipulation\Pass\AvoidMethodClashPass;
use function file_get_contents;
class StringManipulationGenerator implements Generator
{
protected $passes = array();
/**
* @var list<Pass>
*/
protected $passes = [];
/**
* @var string
*/
private $code;
/**
* @param list<Pass> $passes
*/
public function __construct(array $passes)
{
$this->passes = $passes;
$this->code = file_get_contents(__DIR__ . '/../Mock.php');
}
/**
* @param Pass $pass
* @return void
*/
public function addPass(Pass $pass)
{
$this->passes[] = $pass;
}
/**
* @return MockDefinition
*/
public function generate(MockConfiguration $config)
{
$className = $config->getName() ?: $config->generateName();
$namedConfig = $config->rename($className);
$code = $this->code;
foreach ($this->passes as $pass) {
$code = $pass->apply($code, $namedConfig);
}
return new MockDefinition($namedConfig, $code);
}
/**
* Creates a new StringManipulationGenerator with the default passes
@@ -60,30 +96,7 @@ class StringManipulationGenerator implements Generator
new RemoveBuiltinMethodsThatAreFinalPass(),
new RemoveDestructorPass(),
new ConstantsPass(),
new ClassAttributesPass(),
]);
}
public function __construct(array $passes)
{
$this->passes = $passes;
}
public function generate(MockConfiguration $config)
{
$code = file_get_contents(__DIR__ . '/../Mock.php');
$className = $config->getName() ?: $config->generateName();
$namedConfig = $config->rename($className);
foreach ($this->passes as $pass) {
$code = $pass->apply($code, $namedConfig);
}
return new MockDefinition($namedConfig, $code);
}
public function addPass(Pass $pass)
{
$this->passes[] = $pass;
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
@@ -23,36 +13,42 @@ namespace Mockery\Generator;
interface TargetClassInterface
{
/**
* Returns a new instance of the current
* TargetClassInterface's
* implementation.
* Returns a new instance of the current TargetClassInterface's implementation.
*
* @param class-string $name
*
* @param string $name
* @return TargetClassInterface
*/
public static function factory($name);
/**
* Returns the targetClass's name.
* Returns the targetClass's attributes.
*
* @return string
* @return array<class-string>
*/
public function getName();
/**
* Returns the targetClass's methods.
*
* @return array
*/
public function getMethods();
public function getAttributes();
/**
* Returns the targetClass's interfaces.
*
* @return array
* @return array<TargetClassInterface>
*/
public function getInterfaces();
/**
* Returns the targetClass's methods.
*
* @return array<Method>
*/
public function getMethods();
/**
* Returns the targetClass's name.
*
* @return class-string
*/
public function getName();
/**
* Returns the targetClass's namespace name.
*
@@ -67,41 +63,42 @@ interface TargetClassInterface
*/
public function getShortName();
/**
* Returns whether the targetClass has
* an internal ancestor.
*
* @return bool
*/
public function hasInternalAncestor();
/**
* Returns whether the targetClass is in
* the passed interface.
*
* @param class-string|string $interface
*
* @return bool
*/
public function implementsInterface($interface);
/**
* Returns whether the targetClass is in namespace.
*
* @return bool
*/
public function inNamespace();
/**
* Returns whether the targetClass is abstract.
*
* @return boolean
* @return bool
*/
public function isAbstract();
/**
* Returns whether the targetClass is final.
*
* @return boolean
* @return bool
*/
public function isFinal();
/**
* Returns whether the targetClass is in namespace.
*
* @return boolean
*/
public function inNamespace();
/**
* Returns whether the targetClass is in
* the passed interface.
*
* @param mixed $interface
* @return boolean
*/
public function implementsInterface($interface);
/**
* Returns whether the targetClass has
* an internal ancestor.
*
* @return boolean
*/
public function hasInternalAncestor();
}

View File

@@ -1,94 +1,141 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Generator;
use function array_pop;
use function explode;
use function implode;
use function ltrim;
class UndefinedTargetClass implements TargetClassInterface
{
/**
* @var class-string
*/
private $name;
/**
* @param class-string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* @return class-string
*/
public function __toString()
{
return $this->name;
}
/**
* @param class-string $name
* @return self
*/
public static function factory($name)
{
return new self($name);
}
/**
* @return list<class-string>
*/
public function getAttributes()
{
return [];
}
/**
* @return list<self>
*/
public function getInterfaces()
{
return [];
}
/**
* @return list<Method>
*/
public function getMethods()
{
return [];
}
/**
* @return class-string
*/
public function getName()
{
return $this->name;
}
public function isAbstract()
{
return false;
}
public function isFinal()
{
return false;
}
public function getMethods()
{
return array();
}
public function getInterfaces()
{
return array();
}
/**
* @return string
*/
public function getNamespaceName()
{
$parts = explode("\\", ltrim($this->getName(), "\\"));
$parts = explode('\\', ltrim($this->getName(), '\\'));
array_pop($parts);
return implode("\\", $parts);
}
public function inNamespace()
{
return $this->getNamespaceName() !== '';
return implode('\\', $parts);
}
/**
* @return string
*/
public function getShortName()
{
$parts = explode("\\", $this->getName());
$parts = explode('\\', $this->getName());
return array_pop($parts);
}
public function implementsInterface($interface)
{
return false;
}
/**
* @return bool
*/
public function hasInternalAncestor()
{
return false;
}
public function __toString()
/**
* @param class-string $interface
* @return bool
*/
public function implementsInterface($interface)
{
return $this->name;
return false;
}
/**
* @return bool
*/
public function inNamespace()
{
return $this->getNamespaceName() !== '';
}
/**
* @return bool
*/
public function isAbstract()
{
return false;
}
/**
* @return bool
*/
public function isFinal()
{
return false;
}
}

View File

@@ -1,33 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Closure;
/**
* @method \Mockery\Expectation withArgs(\Closure|array $args)
* @method Expectation withArgs(array|Closure $args)
*/
class HigherOrderMessage
{
private $mock;
/**
* @var string
*/
private $method;
/**
* @var LegacyMockInterface|MockInterface
*/
private $mock;
public function __construct(MockInterface $mock, $method)
{
$this->mock = $mock;
@@ -35,7 +34,10 @@ class HigherOrderMessage
}
/**
* @return \Mockery\Expectation
* @param string $method
* @param array $args
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function __call($method, $args)
{
@@ -44,6 +46,7 @@ class HigherOrderMessage
}
$expectation = $this->mock->{$this->method}($method);
return $expectation->withArgs($args);
}
}

View File

@@ -1,112 +1,56 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* Mockery (https://docs.mockery.io/)
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Closure;
use Exception;
use InvalidArgumentException;
use ReflectionClass;
use UnexpectedValueException;
use InvalidArgumentException;
use function class_exists;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function strlen;
use function unserialize;
/**
* This is a trimmed down version of https://github.com/doctrine/instantiator,
* basically without the caching
*
* @author Marco Pivetta <ocramius@gmail.com>
* This is a trimmed down version of https://github.com/doctrine/instantiator, without the caching mechanism.
*/
final class Instantiator
{
/**
* {@inheritDoc}
*/
public function instantiate($className)
{
$factory = $this->buildFactory($className);
$instance = $factory();
return $instance;
}
/**
* Builds a {@see \Closure} capable of instantiating the given $className without
* invoking its constructor.
* @template TClass of object
*
* @param string $className
*
* @return Closure
*/
private function buildFactory($className)
{
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return function () use ($reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
};
}
$serializedString = sprintf(
'O:%d:"%s":0:{}',
strlen($className),
$className
);
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
return function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @param string $className
*
* @return ReflectionClass
* @param class-string<TClass> $className
*
* @throws InvalidArgumentException
* @throws UnexpectedValueException
*
* @return TClass
*/
private function getReflectionClass($className)
public function instantiate($className): object
{
if (! class_exists($className)) {
throw new InvalidArgumentException("Class:$className does not exist");
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw new InvalidArgumentException("Class:$className is an abstract class");
}
return $reflection;
return $this->buildFactory($className)();
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString)
{
set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) {
private function attemptInstantiationViaUnSerialization(
ReflectionClass $reflectionClass,
string $serializedString
): void {
set_error_handler(static function ($code, $message, $file, $line) use ($reflectionClass, &$error): void {
$msg = sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered in file "%s" at line "%d"',
$reflectionClass->getName(),
@@ -114,42 +58,75 @@ final class Instantiator
$line
);
$error = new UnexpectedValueException($msg, 0, new \Exception($message, $code));
$error = new UnexpectedValueException($msg, 0, new Exception($message, $code));
});
try {
unserialize($serializedString);
} catch (\Exception $exception) {
} catch (Exception $exception) {
restore_error_handler();
throw new UnexpectedValueException("An exception was raised while trying to instantiate an instance of \"{$reflectionClass->getName()}\" via un-serialization", 0, $exception);
throw new UnexpectedValueException(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
$reflectionClass->getName()
),
0,
$exception
);
}
restore_error_handler();
if ($error) {
if ($error instanceof UnexpectedValueException) {
throw $error;
}
}
/**
* @param ReflectionClass $reflectionClass
*
* @return bool
* Builds a {@see Closure} capable of instantiating the given $className without invoking its constructor.
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass)
private function buildFactory(string $className): Closure
{
return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return static function () use ($reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
};
}
$serializedString = sprintf('O:%d:"%s":0:{}', strlen($className), $className);
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
return static function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @throws InvalidArgumentException
*/
private function getReflectionClass(string $className): ReflectionClass
{
if (! class_exists($className)) {
throw new InvalidArgumentException(sprintf('Class:%s does not exist', $className));
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw new InvalidArgumentException(sprintf('Class:%s is an abstract class', $className));
}
return $reflection;
}
/**
* Verifies whether the given class is to be considered internal
*
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass)
private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
{
do {
if ($reflectionClass->isInternal()) {
@@ -159,4 +136,12 @@ final class Instantiator
return false;
}
/**
* Verifies if the class is instantiable via reflection
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
{
return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal());
}
}

View File

@@ -1,112 +1,20 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Closure;
use Throwable;
interface LegacyMockInterface
{
/**
* Alternative setup method to constructor
*
* @param \Mockery\Container $container
* @param object $partialObject
* @return void
*/
public function mockery_init(\Mockery\Container $container = null, $partialObject = null);
/**
* Set expected method calls
*
* @param string|array ...$methodNames one or many methods that are expected to be called in this mock
*
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldReceive(...$methodNames);
/**
* Shortcut method for setting an expectation that a method should not be called.
*
* @param string|array ...$methodNames one or many methods that are expected not to be called in this mock
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames);
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
* @param String $method name of the method to be mocked
*/
public function shouldAllowMockingMethod($method);
/**
* Set mock to ignore unexpected methods and return Undefined class
* @param mixed $returnValue the default return value for calls to missing functions on this mock
* @return Mock
*/
public function shouldIgnoreMissing($returnValue = null);
/**
* @return Mock
*/
public function shouldAllowMockingProtectedMethods();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return Mock
*/
public function shouldDeferMissing();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @return Mock
*/
public function makePartial();
/**
* @param null|string $method
* @param null|array|Closure $args
* @return mixed
*/
public function shouldHaveReceived($method, $args = null);
/**
* @return mixed
*/
public function shouldHaveBeenCalled();
/**
* @param null|string $method
* @param null|array|Closure $args
* @return mixed
*/
public function shouldNotHaveReceived($method, $args = null);
/**
* @param array $args (optional)
* @return mixed
*/
public function shouldNotHaveBeenCalled(array $args = null);
/**
* In the event shouldReceive() accepting an array of methods/returns
* this method will switch them from normal expectations to default
@@ -117,19 +25,11 @@ interface LegacyMockInterface
public function byDefault();
/**
* Iterate across all expectation directors and validate each
* Set mock to defer unexpected methods to its parent if possible
*
* @throws \Mockery\CountValidator\Exception
* @return void
* @return self
*/
public function mockery_verify();
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown();
public function makePartial();
/**
* Fetch the next available allocation order number
@@ -139,26 +39,23 @@ interface LegacyMockInterface
public function mockery_allocateOrder();
/**
* Set ordering for a group
* Find an expectation matching the given method and arguments
*
* @param mixed $group
* @param int $order
* @template TMixed
*
* @param string $method
* @param array<TMixed> $args
*
* @return null|Expectation
*/
public function mockery_setGroup($group, $order);
public function mockery_findExpectation($method, array $args);
/**
* Fetch array of ordered groups
* Return the container for this mock
*
* @return array
* @return Container
*/
public function mockery_getGroups();
/**
* Set current ordered number
*
* @param int $order
*/
public function mockery_setCurrentOrder($order);
public function mockery_getContainer();
/**
* Get current ordered number
@@ -167,16 +64,6 @@ interface LegacyMockInterface
*/
public function mockery_getCurrentOrder();
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
* @throws \Mockery\Exception
* @return void
*/
public function mockery_validateOrder($method, $order);
/**
* Gets the count of expectations for this mock
*
@@ -187,34 +74,28 @@ interface LegacyMockInterface
/**
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
*/
public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director);
/**
* Return the expectations director for the given method
* @param string $method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return null|ExpectationDirector
*/
public function mockery_getExpectationsFor($method);
/**
* Find an expectation matching the given method and arguments
* Fetch array of ordered groups
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
* @return array<string,int>
*/
public function mockery_findExpectation($method, array $args);
public function mockery_getGroups();
/**
* Return the container for this mock
*
* @return \Mockery\Container
* @return string[]
*/
public function mockery_getContainer();
public function mockery_getMockableMethods();
/**
* @return array
*/
public function mockery_getMockableProperties();
/**
* Return the name for this mock
@@ -224,17 +105,154 @@ interface LegacyMockInterface
public function mockery_getName();
/**
* @return array
* Alternative setup method to constructor
*
* @param object $partialObject
*
* @return void
*/
public function mockery_getMockableProperties();
/**
* @return string[]
*/
public function mockery_getMockableMethods();
public function mockery_init(?Container $container = null, $partialObject = null);
/**
* @return bool
*/
public function mockery_isAnonymous();
/**
* Set current ordered number
*
* @param int $order
*
* @return int
*/
public function mockery_setCurrentOrder($order);
/**
* Return the expectations director for the given method
*
* @param string $method
*
* @return null|ExpectationDirector
*/
public function mockery_setExpectationsFor($method, ExpectationDirector $director);
/**
* Set ordering for a group
*
* @param string $group
* @param int $order
*
* @return void
*/
public function mockery_setGroup($group, $order);
/**
* Tear down tasks for this mock
*
* @return void
*/
public function mockery_teardown();
/**
* Validate the current mock's ordering
*
* @param string $method
* @param int $order
*
* @throws Exception
*
* @return void
*/
public function mockery_validateOrder($method, $order);
/**
* Iterate across all expectation directors and validate each
*
* @throws Throwable
*
* @return void
*/
public function mockery_verify();
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
*
* @param string $method the method name to be mocked
* @return self
*/
public function shouldAllowMockingMethod($method);
/**
* @return self
*/
public function shouldAllowMockingProtectedMethods();
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return self
*/
public function shouldDeferMissing();
/**
* @return self
*/
public function shouldHaveBeenCalled();
/**
* @template TMixed
* @param string $method
* @param null|array<TMixed>|Closure $args
*
* @return self
*/
public function shouldHaveReceived($method, $args = null);
/**
* Set mock to ignore unexpected methods and return Undefined class
*
* @template TReturnValue
*
* @param null|TReturnValue $returnValue the default return value for calls to missing functions on this mock
*
* @return self
*/
public function shouldIgnoreMissing($returnValue = null);
/**
* @template TMixed
* @param null|array<TMixed> $args (optional)
*
* @return self
*/
public function shouldNotHaveBeenCalled(?array $args = null);
/**
* @template TMixed
* @param string $method
* @param null|array<TMixed>|Closure $args
*
* @return self
*/
public function shouldNotHaveReceived($method, $args = null);
/**
* Shortcut method for setting an expectation that a method should not be called.
*
* @param string ...$methodNames one or many methods that are expected not to be called in this mock
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames);
/**
* Set expected method calls
*
* @param string ...$methodNames one or many methods that are expected to be called in this mock
*
* @return Expectation|ExpectationInterface|HigherOrderMessage
*/
public function shouldReceive(...$methodNames);
}

View File

@@ -1,36 +1,32 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Loader;
use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;
use function class_exists;
class EvalLoader implements Loader
{
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
eval("?>" . $definition->getCode());
eval('?>' . $definition->getCode());
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Loader;
@@ -24,5 +14,10 @@ use Mockery\Generator\MockDefinition;
interface Loader
{
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition);
}

View File

@@ -1,46 +1,80 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Loader;
use Mockery\Generator\MockDefinition;
use Mockery\Loader\Loader;
use function array_diff;
use function class_exists;
use function file_exists;
use function file_put_contents;
use function glob;
use function realpath;
use function sprintf;
use function sys_get_temp_dir;
use function uniqid;
use function unlink;
use const DIRECTORY_SEPARATOR;
class RequireLoader implements Loader
{
/**
* @var string
*/
protected $lastPath = '';
/**
* @var string
*/
protected $path;
/**
* @param string|null $path
*/
public function __construct($path = null)
{
$this->path = realpath($path) ?: sys_get_temp_dir();
if ($path === null) {
$path = sys_get_temp_dir();
}
$this->path = realpath($path);
}
public function __destruct()
{
$files = array_diff(glob($this->path . DIRECTORY_SEPARATOR . 'Mockery_*.php') ?: [], [$this->lastPath]);
foreach ($files as $file) {
@unlink($file);
}
}
/**
* Load the given mock definition
*
* @return void
*/
public function load(MockDefinition $definition)
{
if (class_exists($definition->getClassName(), false)) {
return;
}
$tmpfname = $this->path . DIRECTORY_SEPARATOR . "Mockery_" . uniqid() . ".php";
file_put_contents($tmpfname, $definition->getCode());
$this->lastPath = sprintf('%s%s%s.php', $this->path, DIRECTORY_SEPARATOR, uniqid('Mockery_', false));
require $tmpfname;
file_put_contents($this->lastPath, $definition->getCode());
if (file_exists($this->lastPath)) {
require $this->lastPath;
}
}
}

View File

@@ -1,38 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class AndAnyOtherArgs extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* Return a string representation of this Matcher
*
@@ -42,4 +21,18 @@ class AndAnyOtherArgs extends MatcherAbstract
{
return '<AndAnyOthers>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
}

View File

@@ -1,38 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class Any extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* Return a string representation of this Matcher
*
@@ -42,4 +21,18 @@ class Any extends MatcherAbstract
{
return '<Any>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
}

View File

@@ -1,40 +1,31 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class AnyArgs extends MatcherAbstract implements ArgumentListMatcher
{
public function __toString()
{
return '<Any Arguments>';
}
/**
* @inheritdoc
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return true;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<Any Arguments>';
}
}

View File

@@ -1,39 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function in_array;
class AnyOf extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return in_array($actual, $this->_expected, true);
}
/**
* Return a string representation of this Matcher
*
@@ -43,4 +23,19 @@ class AnyOf extends MatcherAbstract
{
return '<AnyOf>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return in_array($actual, $this->_expected, true);
}
}

View File

@@ -1,21 +1,11 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;

View File

@@ -1,40 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class Closure extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
$closure = $this->_expected;
$result = $closure($actual);
return $result === true;
}
/**
* Return a string representation of this Matcher
*
@@ -44,4 +21,18 @@ class Closure extends MatcherAbstract
{
return '<Closure===true>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return ($this->_expected)($actual) === true;
}
}

View File

@@ -1,31 +1,42 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function array_values;
use function implode;
class Contains extends MatcherAbstract
{
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$elements = [];
foreach ($this->_expected as $v) {
$elements[] = (string) $v;
}
return '<Contains[' . implode(', ', $elements) . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
@@ -39,26 +50,12 @@ class Contains extends MatcherAbstract
break;
}
}
if ($match === false) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
* @return string
*/
public function __toString()
{
$return = '<Contains[';
$elements = array();
foreach ($this->_expected as $v) {
$elements[] = (string) $v;
}
$return .= implode(', ', $elements) . ']>';
return $return;
}
}

View File

@@ -1,46 +1,21 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function implode;
use function is_object;
use function method_exists;
class Ducktype extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if (!is_object($actual)) {
return false;
}
foreach ($this->_expected as $method) {
if (!method_exists($actual, $method)) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
@@ -50,4 +25,28 @@ class Ducktype extends MatcherAbstract
{
return '<Ducktype[' . implode(', ', $this->_expected) . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_object($actual)) {
return false;
}
foreach ($this->_expected as $method) {
if (! method_exists($actual, $method)) {
return false;
}
}
return true;
}
}

View File

@@ -1,38 +1,23 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use ArrayAccess;
use function array_key_exists;
use function is_array;
use function sprintf;
class HasKey extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return array_key_exists($this->_expected, $actual);
}
/**
* Return a string representation of this Matcher
*
@@ -40,6 +25,24 @@ class HasKey extends MatcherAbstract
*/
public function __toString()
{
return "<HasKey[$this->_expected]>";
return sprintf('<HasKey[%s]>', $this->_expected);
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_array($actual) && ! $actual instanceof ArrayAccess) {
return false;
}
return array_key_exists($this->_expected, (array) $actual);
}
}

View File

@@ -1,38 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use ArrayAccess;
use function in_array;
use function is_array;
class HasValue extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return in_array($this->_expected, $actual);
}
/**
* Return a string representation of this Matcher
*
@@ -40,7 +24,24 @@ class HasValue extends MatcherAbstract
*/
public function __toString()
{
$return = '<HasValue[' . (string) $this->_expected . ']>';
return $return;
return '<HasValue[' . (string) $this->_expected . ']>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_array($actual) && ! $actual instanceof ArrayAccess) {
return false;
}
return in_array($this->_expected, (array) $actual, true);
}
}

View File

@@ -1,58 +1,39 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
abstract class MatcherAbstract
/**
* @deprecated Implement \Mockery\Matcher\MatcherInterface instead of extending this class
* @see https://github.com/mockery/mockery/pull/1338
*/
abstract class MatcherAbstract implements MatcherInterface
{
/**
* The expected value (or part thereof)
*
* @var mixed
* @template TExpected
*
* @var TExpected
*/
protected $_expected = null;
/**
* Set the expected value
*
* @param mixed $expected
* @template TExpected
*
* @param TExpected $expected
*/
public function __construct($expected = null)
{
$this->_expected = $expected;
}
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @param mixed $actual
* @return bool
*/
abstract public function match(&$actual);
/**
* Return a string representation of this Matcher
*
* @return string
*/
abstract public function __toString();
}

View File

@@ -1,41 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class MultiArgumentClosure extends MatcherAbstract implements ArgumentListMatcher
{
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
$closure = $this->_expected;
return true === call_user_func_array($closure, $actual);
}
/**
* Return a string representation of this Matcher
*
@@ -45,4 +21,20 @@ class MultiArgumentClosure extends MatcherAbstract implements ArgumentListMatche
{
return '<MultiArgumentClosure===true>';
}
/**
* Check if the actual value matches the expected.
* Actual passed by reference to preserve reference trail (where applicable)
* back to the original method parameter.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return ($this->_expected)(...$actual) === true;
}
}

View File

@@ -1,45 +1,22 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function is_object;
/**
* @deprecated 2.0 Due to ambiguity, use Hamcrest or PHPUnit equivalents
* @deprecated 2.0 Due to ambiguity, use PHPUnit equivalents
*/
class MustBe extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if (!is_object($actual)) {
return $this->_expected === $actual;
}
return $this->_expected == $actual;
}
/**
* Return a string representation of this Matcher
*
@@ -49,4 +26,22 @@ class MustBe extends MatcherAbstract
{
return '<MustBe>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (! is_object($actual)) {
return $this->_expected === $actual;
}
return $this->_expected == $actual;
}
}

View File

@@ -1,40 +1,33 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function count;
class NoArgs extends MatcherAbstract implements ArgumentListMatcher
{
/**
* @inheritdoc
*/
public function match(&$actual)
{
return count($actual) == 0;
}
/**
* @inheritdoc
*/
public function __toString()
{
return '<No Arguments>';
}
/**
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return count($actual) === 0;
}
}

View File

@@ -1,39 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class Not extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return $actual !== $this->_expected;
}
/**
* Return a string representation of this Matcher
*
@@ -43,4 +21,19 @@ class Not extends MatcherAbstract
{
return '<Not>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return $actual !== $this->_expected;
}
}

View File

@@ -1,44 +1,17 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
class NotAnyOf extends MatcherAbstract
{
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
foreach ($this->_expected as $exp) {
if ($actual === $exp || $actual == $exp) {
return false;
}
}
return true;
}
/**
* Return a string representation of this Matcher
*
@@ -48,4 +21,25 @@ class NotAnyOf extends MatcherAbstract
{
return '<AnyOf>';
}
/**
* Check if the actual value does not match the expected (in this
* case it's specifically NOT expected).
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
foreach ($this->_expected as $exp) {
if ($actual === $exp || $actual == $exp) {
return false;
}
}
return true;
}
}

View File

@@ -1,38 +1,19 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function preg_match;
class Pattern extends MatcherAbstract
{
/**
* Check if the actual value matches the expected pattern.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
return preg_match($this->_expected, (string) $actual) >= 1;
}
/**
* Return a string representation of this Matcher
*
@@ -42,4 +23,18 @@ class Pattern extends MatcherAbstract
{
return '<Pattern>';
}
/**
* Check if the actual value matches the expected pattern.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
return preg_match($this->_expected, (string) $actual) >= 1;
}
}

View File

@@ -1,33 +1,28 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function array_replace_recursive;
use function implode;
use function is_array;
class Subset extends MatcherAbstract
{
private $expected;
private $strict = true;
/**
* @param array $expected Expected subset of data
* @param bool $strict Whether to run a strict or loose comparison
* @param bool $strict Whether to run a strict or loose comparison
*/
public function __construct(array $expected, $strict = true)
{
@@ -36,13 +31,13 @@ class Subset extends MatcherAbstract
}
/**
* @param array $expected Expected subset of data
* Return a string representation of this Matcher
*
* @return Subset
* @return string
*/
public static function strict(array $expected)
public function __toString()
{
return new static($expected, true);
return '<Subset' . $this->formatArray($this->expected) . '>';
}
/**
@@ -58,12 +53,15 @@ class Subset extends MatcherAbstract
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
if (!is_array($actual)) {
if (! is_array($actual)) {
return false;
}
@@ -75,18 +73,27 @@ class Subset extends MatcherAbstract
}
/**
* Return a string representation of this Matcher
* @param array $expected Expected subset of data
*
* @return Subset
*/
public static function strict(array $expected)
{
return new static($expected, true);
}
/**
* Recursively format an array into the string representation for this matcher
*
* @return string
*/
public function __toString()
protected function formatArray(array $array)
{
$return = '<Subset[';
$elements = array();
foreach ($this->expected as $k=>$v) {
$elements[] = $k . '=' . (string) $v;
$elements = [];
foreach ($array as $k => $v) {
$elements[] = $k . '=' . (is_array($v) ? $this->formatArray($v) : (string) $v);
}
$return .= implode(', ', $elements) . ']>';
return $return;
return '[' . implode(', ', $elements) . ']';
}
}

View File

@@ -1,49 +1,24 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery\Matcher;
use function class_exists;
use function function_exists;
use function interface_exists;
use function is_string;
use function strtolower;
use function ucfirst;
class Type extends MatcherAbstract
{
/**
* Check if the actual value matches the expected.
*
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
if ($this->_expected == 'real') {
$function = 'is_float';
} else {
$function = 'is_' . strtolower($this->_expected);
}
if (function_exists($function)) {
return $function($actual);
} elseif (is_string($this->_expected)
&& (class_exists($this->_expected) || interface_exists($this->_expected))) {
return $actual instanceof $this->_expected;
}
return false;
}
/**
* Return a string representation of this Matcher
*
@@ -53,4 +28,32 @@ class Type extends MatcherAbstract
{
return '<' . ucfirst($this->_expected) . '>';
}
/**
* Check if the actual value matches the expected.
*
* @template TMixed
*
* @param TMixed $actual
*
* @return bool
*/
public function match(&$actual)
{
$function = $this->_expected === 'real' ? 'is_float' : 'is_' . strtolower($this->_expected);
if (function_exists($function)) {
return $function($actual);
}
if (! is_string($this->_expected)) {
return false;
}
if (class_exists($this->_expected) || interface_exists($this->_expected)) {
return $actual instanceof $this->_expected;
}
return false;
}
}

View File

@@ -1,43 +1,50 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class MethodCall
{
private $method;
/**
* @var array
*/
private $args;
/**
* @var string
*/
private $method;
/**
* @param string $method
* @param array $args
*/
public function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
public function getMethod()
{
return $this->method;
}
/**
* @return array
*/
public function getArgs()
{
return $this->args;
}
/**
* @return string
*/
public function getMethod()
{
return $this->method;
}
}

View File

@@ -1,32 +1,34 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Mockery\Container;
use Mockery\CountValidator\Exception;
use Mockery\Exception\BadMethodCallException;
use Mockery\Exception\InvalidOrderException;
use Mockery\Exception\NoMatchingExpectationException;
use Mockery\Expectation;
use Mockery\ExpectationDirector;
use Mockery\ExpectsHigherOrderMessage;
use Mockery\HigherOrderMessage;
use Mockery\LegacyMockInterface;
use Mockery\MethodCall;
use Mockery\MockInterface;
use Mockery\ReceivedMethodCalls;
use Mockery\Reflector;
use Mockery\Undefined;
use Mockery\VerificationDirector;
use Mockery\VerificationExpectation;
#[\AllowDynamicProperties]
class Mock implements MockInterface
{
/**
@@ -34,7 +36,7 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_expectations = array();
protected $_mockery_expectations = [];
/**
* Stores an initial number of expectations that can be manipulated
@@ -101,12 +103,12 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_groups = array();
protected $_mockery_groups = [];
/**
* Mock container containing this mock object
*
* @var \Mockery\Container
* @var Container
*/
protected $_mockery_container = null;
@@ -134,12 +136,12 @@ class Mock implements MockInterface
*
* @var array
*/
protected $_mockery_mockableProperties = array();
protected $_mockery_mockableProperties = [];
/**
* @var array
*/
protected $_mockery_mockableMethods = array();
protected $_mockery_mockableMethods = [];
/**
* Just a local cache for this mock's target's methods
@@ -167,20 +169,24 @@ class Mock implements MockInterface
protected $_mockery_instanceMock = true;
/** @var null|string $parentClass */
private $_mockery_parentClass = null;
/**
* We want to avoid constructors since class is copied to Generator.php
* for inclusion on extending class definitions.
*
* @param \Mockery\Container $container
* @param Container $container
* @param object $partialObject
* @param bool $instanceMock
* @return void
*/
public function mockery_init(\Mockery\Container $container = null, $partialObject = null, $instanceMock = true)
public function mockery_init(?Container $container = null, $partialObject = null, $instanceMock = true)
{
if (is_null($container)) {
$container = new \Mockery\Container();
if (null === $container) {
$container = new Container();
}
$this->_mockery_container = $container;
if (!is_null($partialObject)) {
$this->_mockery_partial = $partialObject;
@@ -195,6 +201,8 @@ class Mock implements MockInterface
}
$this->_mockery_instanceMock = $instanceMock;
$this->_mockery_parentClass = get_parent_class($this);
}
/**
@@ -202,54 +210,54 @@ class Mock implements MockInterface
*
* @param string ...$methodNames one or many methods that are expected to be called in this mock
*
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
* @return ExpectationInterface|Expectation|HigherOrderMessage
*/
public function shouldReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldReceive");
if ($methodNames === []) {
return new HigherOrderMessage($this, 'shouldReceive');
}
foreach ($methodNames as $method) {
if ("" == $method) {
throw new \InvalidArgumentException("Received empty method name");
if ('' === $method) {
throw new \InvalidArgumentException('Received empty method name');
}
}
$self = $this;
$allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods;
$lastExpectation = \Mockery::parseShouldReturnArgs(
return \Mockery::parseShouldReturnArgs(
$this,
$methodNames,
function ($method) use ($self, $allowMockingProtectedMethods) {
static function ($method) use ($self, $allowMockingProtectedMethods) {
$rm = $self->mockery_getMethod($method);
if ($rm) {
if ($rm->isPrivate()) {
throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method");
throw new \InvalidArgumentException($method . '() cannot be mocked as it is a private method');
}
if (!$allowMockingProtectedMethods && $rm->isProtected()) {
throw new \InvalidArgumentException("$method() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods.");
throw new \InvalidArgumentException($method . '() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods.');
}
}
$director = $self->mockery_getExpectationsFor($method);
if (!$director) {
$director = new \Mockery\ExpectationDirector($method, $self);
$director = new ExpectationDirector($method, $self);
$self->mockery_setExpectationsFor($method, $director);
}
$expectation = new \Mockery\Expectation($self, $method);
$expectation = new Expectation($self, $method);
$director->addExpectation($expectation);
return $expectation;
}
);
return $lastExpectation;
}
// start method allows
/**
* @param mixed $something String method name or map of method => return
* @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
* @return self|ExpectationInterface|Expectation|HigherOrderMessage
*/
public function allows($something = [])
{
@@ -267,14 +275,14 @@ class Mock implements MockInterface
return $this;
}
// end method allows
// end method allows
// start method expects
/**
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|ExpectsHigherOrderMessage
*/
/**
* @param mixed $something String method name (optional)
* @return ExpectationInterface|Expectation|ExpectsHigherOrderMessage
*/
public function expects($something = null)
{
if (is_string($something)) {
@@ -283,29 +291,32 @@ class Mock implements MockInterface
return new ExpectsHigherOrderMessage($this);
}
// end method expects
// end method expects
/**
* Shortcut method for setting an expectation that a method should not be called.
*
* @param string ...$methodNames one or many methods that are expected not to be called in this mock
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
* @return ExpectationInterface|Expectation|HigherOrderMessage
*/
public function shouldNotReceive(...$methodNames)
{
if (count($methodNames) === 0) {
return new HigherOrderMessage($this, "shouldNotReceive");
if ($methodNames === []) {
return new HigherOrderMessage($this, 'shouldNotReceive');
}
$expectation = call_user_func_array(array($this, 'shouldReceive'), $methodNames);
$expectation = call_user_func_array(function (string $methodNames) {
return $this->shouldReceive($methodNames);
}, $methodNames);
$expectation->never();
return $expectation;
}
/**
* Allows additional methods to be mocked that do not explicitly exist on mocked class
* @param String $method name of the method to be mocked
* @return Mock
*
* @param string $method name of the method to be mocked
* @return Mock|MockInterface|LegacyMockInterface
*/
public function shouldAllowMockingMethod($method)
{
@@ -317,7 +328,7 @@ class Mock implements MockInterface
* Set mock to ignore unexpected methods and return Undefined class
* @param mixed $returnValue the default return value for calls to missing functions on this mock
* @param bool $recursive Specify if returned mocks should also have shouldIgnoreMissing set
* @return Mock
* @return static
*/
public function shouldIgnoreMissing($returnValue = null, $recursive = false)
{
@@ -330,12 +341,12 @@ class Mock implements MockInterface
public function asUndefined()
{
$this->_mockery_ignoreMissing = true;
$this->_mockery_defaultReturnValue = new \Mockery\Undefined();
$this->_mockery_defaultReturnValue = new Undefined();
return $this;
}
/**
* @return Mock
* @return static
*/
public function shouldAllowMockingProtectedMethods()
{
@@ -360,7 +371,7 @@ class Mock implements MockInterface
*
* @deprecated 2.0.0 Please use makePartial() instead
*
* @return Mock
* @return static
*/
public function shouldDeferMissing()
{
@@ -373,7 +384,7 @@ class Mock implements MockInterface
* It was an alias for shouldDeferMissing(), which will be removed
* in 2.0.0.
*
* @return Mock
* @return static
*/
public function makePartial()
{
@@ -396,6 +407,7 @@ class Mock implements MockInterface
$exp->byDefault();
}
}
return $this;
}
@@ -415,15 +427,16 @@ class Mock implements MockInterface
/**
* Forward calls to this magic method to the __call method
*/
#[\ReturnTypeWillChange]
public function __toString()
{
return $this->__call('__toString', array());
return $this->__call('__toString', []);
}
/**
* Iterate across all expectation directors and validate each
*
* @throws \Mockery\CountValidator\Exception
* @throws Exception
* @return void
*/
public function mockery_verify()
@@ -431,10 +444,12 @@ class Mock implements MockInterface
if ($this->_mockery_verified) {
return;
}
if (isset($this->_mockery_ignoreVerification)
if (property_exists($this, '_mockery_ignoreVerification') && $this->_mockery_ignoreVerification !== null
&& $this->_mockery_ignoreVerification == true) {
return;
}
$this->_mockery_verified = true;
foreach ($this->_mockery_expectations as $director) {
$director->verify();
@@ -467,7 +482,7 @@ class Mock implements MockInterface
*/
public function mockery_allocateOrder()
{
$this->_mockery_allocatedOrder += 1;
++$this->_mockery_allocatedOrder;
return $this->_mockery_allocatedOrder;
}
@@ -524,8 +539,8 @@ class Mock implements MockInterface
public function mockery_validateOrder($method, $order)
{
if ($order < $this->_mockery_currentOrder) {
$exception = new \Mockery\Exception\InvalidOrderException(
'Method ' . __CLASS__ . '::' . $method . '()'
$exception = new InvalidOrderException(
'Method ' . self::class . '::' . $method . '()'
. ' called out of order: expected order '
. $order . ', was ' . $this->_mockery_currentOrder
);
@@ -535,6 +550,7 @@ class Mock implements MockInterface
->setActualOrder($this->_mockery_currentOrder);
throw $exception;
}
$this->mockery_setCurrentOrder($order);
}
@@ -549,6 +565,7 @@ class Mock implements MockInterface
foreach ($this->_mockery_expectations as $director) {
$count += $director->getExpectationCount();
}
return $count;
}
@@ -556,9 +573,9 @@ class Mock implements MockInterface
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return ExpectationDirector|null
*/
public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
public function mockery_setExpectationsFor($method, ExpectationDirector $director)
{
$this->_mockery_expectations[$method] = $director;
}
@@ -567,7 +584,7 @@ class Mock implements MockInterface
* Return the expectations director for the given method
*
* @var string $method
* @return \Mockery\ExpectationDirector|null
* @return ExpectationDirector|null
*/
public function mockery_getExpectationsFor($method)
{
@@ -581,13 +598,14 @@ class Mock implements MockInterface
*
* @var string $method
* @var array $args
* @return \Mockery\Expectation|null
* @return Expectation|null
*/
public function mockery_findExpectation($method, array $args)
{
if (!isset($this->_mockery_expectations[$method])) {
return null;
}
$director = $this->_mockery_expectations[$method];
return $director->findExpectation($args);
@@ -596,7 +614,7 @@ class Mock implements MockInterface
/**
* Return the container for this mock
*
* @return \Mockery\Container
* @return Container
*/
public function mockery_getContainer()
{
@@ -610,7 +628,7 @@ class Mock implements MockInterface
*/
public function mockery_getName()
{
return __CLASS__;
return self::class;
}
/**
@@ -623,11 +641,19 @@ class Mock implements MockInterface
public function __isset($name)
{
if (false === stripos($name, '_mockery_') && get_parent_class($this) && method_exists(get_parent_class($this), '__isset')) {
return call_user_func('parent::__isset', $name);
if (false !== stripos($name, '_mockery_')) {
return false;
}
return false;
if (!$this->_mockery_parentClass) {
return false;
}
if (!method_exists($this->_mockery_parentClass, '__isset')) {
return false;
}
return call_user_func($this->_mockery_parentClass . '::__isset', $name);
}
public function mockery_getExpectations()
@@ -646,10 +672,11 @@ class Mock implements MockInterface
*/
public function mockery_callSubjectMethod($name, array $args)
{
if (!method_exists($this, $name) && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) {
return call_user_func('parent::__call', $name, $args);
if (!method_exists($this, $name) && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
return call_user_func($this->_mockery_parentClass . '::__call', $name, $args);
}
return call_user_func_array('parent::' . $name, $args);
return call_user_func_array($this->_mockery_parentClass . '::' . $name, $args);
}
/**
@@ -668,7 +695,7 @@ class Mock implements MockInterface
$rfc = new \ReflectionClass($this);
// PHP 8 has Stringable interface
$interfaces = array_filter($rfc->getInterfaces(), function ($i) {
$interfaces = array_filter($rfc->getInterfaces(), static function ($i) {
return $i->getName() !== 'Stringable';
});
@@ -729,6 +756,8 @@ class Mock implements MockInterface
case 'int': return 0;
case 'float': return 0.0;
case 'bool': return false;
case 'true': return true;
case 'false': return false;
case 'array':
case 'iterable':
@@ -736,12 +765,14 @@ class Mock implements MockInterface
case 'callable':
case '\Closure':
return function () {
return static function () : void {
};
case '\Traversable':
case '\Generator':
$generator = function () { yield; };
$generator = static function () {
yield;
};
return $generator();
case 'void':
@@ -755,6 +786,7 @@ class Mock implements MockInterface
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
default:
@@ -762,6 +794,7 @@ class Mock implements MockInterface
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
}
}
@@ -769,65 +802,67 @@ class Mock implements MockInterface
public function shouldHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldHaveReceived");
return new HigherOrderMessage($this, 'shouldHaveReceived');
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
$expectation = new VerificationExpectation($this, $method);
if (null !== $args) {
$expectation->withArgs($args);
}
$expectation->atLeast()->once();
$director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
$this->_mockery_expectations_count++;
$director = new VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
++$this->_mockery_expectations_count;
$director->verify();
return $director;
}
public function shouldHaveBeenCalled()
{
return $this->shouldHaveReceived("__invoke");
return $this->shouldHaveReceived('__invoke');
}
public function shouldNotHaveReceived($method = null, $args = null)
{
if ($method === null) {
return new HigherOrderMessage($this, "shouldNotHaveReceived");
return new HigherOrderMessage($this, 'shouldNotHaveReceived');
}
$expectation = new \Mockery\VerificationExpectation($this, $method);
$expectation = new VerificationExpectation($this, $method);
if (null !== $args) {
$expectation->withArgs($args);
}
$expectation->never();
$director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
$this->_mockery_expectations_count++;
$director = new VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation);
++$this->_mockery_expectations_count;
$director->verify();
return null;
}
public function shouldNotHaveBeenCalled(array $args = null)
public function shouldNotHaveBeenCalled(?array $args = null)
{
return $this->shouldNotHaveReceived("__invoke", $args);
return $this->shouldNotHaveReceived('__invoke', $args);
}
protected static function _mockery_handleStaticMethodCall($method, array $args)
{
$associatedRealObject = \Mockery::fetchMock(__CLASS__);
$associatedRealObject = \Mockery::fetchMock(self::class);
try {
return $associatedRealObject->__call($method, $args);
} catch (BadMethodCallException $e) {
} catch (BadMethodCallException $badMethodCallException) {
throw new BadMethodCallException(
'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method
. '() does not exist on this mock object',
0,
$e
$badMethodCallException
);
}
}
protected function _mockery_getReceivedMethodCalls()
{
return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls();
return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new ReceivedMethodCalls();
}
/**
@@ -841,6 +876,7 @@ class Mock implements MockInterface
if (!isset($this->_mockery_expectations['__construct']) /* _mockery_handleMethodCall runs the other checks */) {
return;
}
$this->_mockery_handleMethodCall('__construct', $args);
}
@@ -853,16 +889,12 @@ class Mock implements MockInterface
$lowerCasedMockeryExpectations = array_change_key_case($this->_mockery_expectations, CASE_LOWER);
$lowerCasedMethod = strtolower($method);
if (isset($lowerCasedMockeryExpectations[$lowerCasedMethod])) {
return $lowerCasedMockeryExpectations[$lowerCasedMethod];
}
return null;
return $lowerCasedMockeryExpectations[$lowerCasedMethod] ?? null;
}
protected function _mockery_handleMethodCall($method, array $args)
{
$this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args));
$this->_mockery_getReceivedMethodCalls()->push(new MethodCall($method, $args));
$rm = $this->mockery_getMethod($method);
if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) {
@@ -879,7 +911,11 @@ class Mock implements MockInterface
// noop - there is no hasPrototype method
}
return call_user_func_array("parent::$method", $args);
if (null === $this->_mockery_parentClass) {
$this->_mockery_parentClass = get_parent_class($this);
}
return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
$handler = $this->_mockery_findExpectedMethodHandler($method);
@@ -887,7 +923,7 @@ class Mock implements MockInterface
if ($handler !== null && !$this->_mockery_disableExpectationMatching) {
try {
return $handler->call($args);
} catch (\Mockery\Exception\NoMatchingExpectationException $e) {
} catch (NoMatchingExpectationException $e) {
if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) {
throw $e;
}
@@ -895,36 +931,43 @@ class Mock implements MockInterface
}
if (!is_null($this->_mockery_partial) &&
(method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call'))
) {
return call_user_func_array(array($this->_mockery_partial, $method), $args);
} elseif ($this->_mockery_deferMissing && is_callable("parent::$method")
&& (!$this->hasMethodOverloadingInParentClass() || (get_parent_class($this) && method_exists(get_parent_class($this), $method)))) {
return call_user_func_array("parent::$method", $args);
} elseif ($this->_mockery_deferMissing && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) {
return call_user_func('parent::__call', $method, $args);
} elseif ($method == '__toString') {
(method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call'))) {
return $this->_mockery_partial->{$method}(...$args);
}
if ($this->_mockery_deferMissing && is_callable($this->_mockery_parentClass . '::' . $method)
&& (!$this->hasMethodOverloadingInParentClass() || ($this->_mockery_parentClass && method_exists($this->_mockery_parentClass, $method)))) {
return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
if ($this->_mockery_deferMissing && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
return call_user_func($this->_mockery_parentClass . '::__call', $method, $args);
}
if ($method === '__toString') {
// __toString is special because we force its addition to the class API regardless of the
// original implementation. Thus, we should always return a string rather than honor
// _mockery_ignoreMissing and break the API with an error.
return sprintf("%s#%s", __CLASS__, spl_object_hash($this));
} elseif ($this->_mockery_ignoreMissing) {
if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable("parent::$method")) {
if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) {
return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args);
} elseif (null === $this->_mockery_defaultReturnValue) {
return $this->mockery_returnValueForMethod($method);
}
return $this->_mockery_defaultReturnValue;
}
return sprintf('%s#%s', self::class, spl_object_hash($this));
}
$message = 'Method ' . __CLASS__ . '::' . $method .
if ($this->_mockery_ignoreMissing && (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable($this->_mockery_parentClass . '::' . $method))) {
if ($this->_mockery_defaultReturnValue instanceof Undefined) {
return $this->_mockery_defaultReturnValue->{$method}(...$args);
}
if (null === $this->_mockery_defaultReturnValue) {
return $this->mockery_returnValueForMethod($method);
}
return $this->_mockery_defaultReturnValue;
}
$message = 'Method ' . self::class . '::' . $method .
'() does not exist on this mock object';
if (!is_null($rm)) {
$message = 'Received ' . __CLASS__ .
$message = 'Received ' . self::class .
'::' . $method . '(), but no expectations were specified';
}
@@ -945,7 +988,7 @@ class Mock implements MockInterface
return static::$_mockery_methods;
}
if (isset($this->_mockery_partial)) {
if ($this->_mockery_partial !== null) {
$reflected = new \ReflectionObject($this->_mockery_partial);
} else {
$reflected = new \ReflectionClass($this);
@@ -957,7 +1000,7 @@ class Mock implements MockInterface
private function hasMethodOverloadingInParentClass()
{
// if there's __call any name would be callable
return is_callable('parent::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
return is_callable($this->_mockery_parentClass . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
}
/**
@@ -966,10 +1009,10 @@ class Mock implements MockInterface
private function getNonPublicMethods()
{
return array_map(
function ($method) {
static function ($method) {
return $method->getName();
},
array_filter($this->mockery_getMethods(), function ($method) {
array_filter($this->mockery_getMethods(), static function ($method) {
return !$method->isPublic();
})
);

View File

@@ -1,38 +1,28 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use Mockery\LegacyMockInterface;
interface MockInterface extends LegacyMockInterface
{
/**
* @param mixed $something String method name or map of method => return
* @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage
* @param mixed $something String method name or map of method => return
*
* @return Expectation|ExpectationInterface|HigherOrderMessage|self
*/
public function allows($something = []);
/**
* @param mixed $something String method name (optional)
* @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\ExpectsHigherOrderMessage
* @param mixed $something String method name (optional)
*
* @return Expectation|ExpectationInterface|ExpectsHigherOrderMessage
*/
public function expects($something = null);
}

View File

@@ -1,30 +1,21 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class QuickDefinitionsConfiguration
{
private const QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE = 'QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE';
private const QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION = 'QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION';
private const QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE = 'QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE';
/**
* Defines what a quick definition should produce.
* Possible options are:

View File

@@ -1,28 +1,18 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class ReceivedMethodCalls
{
private $methodCalls = array();
private $methodCalls = [];
public function push(MethodCall $methodCall)
{
@@ -36,7 +26,7 @@ class ReceivedMethodCalls
continue;
}
if (!$expectation->matchArgs($methodCall->getArgs())) {
if (! $expectation->matchArgs($methodCall->getArgs())) {
continue;
}

View File

@@ -1,107 +1,108 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2017 Dave Marshall https://github.com/davedevelopment
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionIntersectionType;
use ReflectionMethod;
use ReflectionNamedType;
use ReflectionParameter;
use ReflectionType;
use ReflectionUnionType;
use function array_diff;
use function array_intersect;
use function array_map;
use function array_merge;
use function get_debug_type;
use function implode;
use function in_array;
use function method_exists;
use function sprintf;
use function strpos;
use const PHP_VERSION_ID;
/**
* @internal
*/
class Reflector
{
/**
* Determine if the parameter is typed as an array.
* List of built-in types.
*
* @param \ReflectionParameter $param
*
* @return bool
* @var list<string>
*/
public static function isArray(\ReflectionParameter $param)
{
$type = $param->getType();
return $type instanceof \ReflectionNamedType && $type->getName();
}
public const BUILTIN_TYPES = ['array', 'bool', 'int', 'float', 'null', 'object', 'string'];
/**
* Compute the string representation for the paramater type.
* List of reserved words.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
* @var list<string>
*/
public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false)
{
if (!$param->hasType()) {
return null;
}
public const RESERVED_WORDS = ['bool', 'true', 'false', 'float', 'int', 'iterable', 'mixed', 'never', 'null', 'object', 'string', 'void'];
$type = $param->getType();
$declaringClass = $param->getDeclaringClass();
$typeHint = self::typeToString($type, $declaringClass);
/**
* Iterable.
*
* @var list<string>
*/
private const ITERABLE = ['iterable'];
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Traversable array.
*
* @var list<string>
*/
private const TRAVERSABLE_ARRAY = ['\Traversable', 'array'];
/**
* Compute the string representation for the return type.
*
* @param \ReflectionParameter $param
* @param bool $withoutNullable
*
* @return string|null
* @return null|string
*/
public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false)
public static function getReturnType(ReflectionMethod $method, $withoutNullable = false)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
if (! $type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type)) {
if (! $type instanceof ReflectionType) {
return null;
}
$typeHint = self::typeToString($type, $method->getDeclaringClass());
$typeHint = self::getTypeFromReflectionType($type, $method->getDeclaringClass());
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
return (! $withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Compute the string representation for the simplest return type.
*
* @param \ReflectionParameter $param
*
* @return string|null
* @return null|string
*/
public static function getSimplestReturnType(\ReflectionMethod $method)
public static function getSimplestReturnType(ReflectionMethod $method)
{
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
if (! $type instanceof ReflectionType && method_exists($method, 'getTentativeReturnType')) {
$type = $method->getTentativeReturnType();
}
if (is_null($type) || $type->allowsNull()) {
if (! $type instanceof ReflectionType || $type->allowsNull()) {
return null;
}
@@ -123,32 +124,139 @@ class Reflector
}
/**
* Get the string representation of the given type.
* Compute the string representation for the paramater type.
*
* @param \ReflectionType $type
* @param string $declaringClass
* @param bool $withoutNullable
*
* @return string|null
* @return null|string
*/
private static function typeToString(\ReflectionType $type, \ReflectionClass $declaringClass)
public static function getTypeHint(ReflectionParameter $param, $withoutNullable = false)
{
return \implode('|', \array_map(function (array $typeInformation) {
return $typeInformation['typeHint'];
}, self::getTypeInformation($type, $declaringClass)));
if (! $param->hasType()) {
return null;
}
$type = $param->getType();
$declaringClass = $param->getDeclaringClass();
$typeHint = self::getTypeFromReflectionType($type, $declaringClass);
return (! $withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
* Determine if the parameter is typed as an array.
*
* @return bool
*/
public static function isArray(ReflectionParameter $param)
{
$type = $param->getType();
return $type instanceof ReflectionNamedType && $type->getName();
}
/**
* Determine if the given type is a reserved word.
*/
public static function isReservedWord(string $type): bool
{
return in_array(strtolower($type), self::RESERVED_WORDS, true);
}
/**
* Format the given type as a nullable type.
*/
private static function formatNullableType(string $typeHint): string
{
if ($typeHint === 'mixed') {
return $typeHint;
}
if (strpos($typeHint, 'null') !== false) {
return $typeHint;
}
if (PHP_VERSION_ID < 80000) {
return sprintf('?%s', $typeHint);
}
return sprintf('%s|null', $typeHint);
}
private static function getTypeFromReflectionType(ReflectionType $type, ReflectionClass $declaringClass): string
{
if ($type instanceof ReflectionNamedType) {
$typeHint = $type->getName();
if ($type->isBuiltin()) {
return $typeHint;
}
if ($typeHint === 'static') {
return $typeHint;
}
// 'self' needs to be resolved to the name of the declaring class
if ($typeHint === 'self') {
$typeHint = $declaringClass->getName();
}
// 'parent' needs to be resolved to the name of the parent class
if ($typeHint === 'parent') {
$typeHint = $declaringClass->getParentClass()->getName();
}
// class names need prefixing with a slash
return sprintf('\\%s', $typeHint);
}
if ($type instanceof ReflectionIntersectionType) {
$types = array_map(
static function (ReflectionType $type) use ($declaringClass): string {
return self::getTypeFromReflectionType($type, $declaringClass);
},
$type->getTypes()
);
return implode('&', $types);
}
if ($type instanceof ReflectionUnionType) {
$types = array_map(
static function (ReflectionType $type) use ($declaringClass): string {
return self::getTypeFromReflectionType($type, $declaringClass);
},
$type->getTypes()
);
$intersect = array_intersect(self::TRAVERSABLE_ARRAY, $types);
if ($intersect === self::TRAVERSABLE_ARRAY) {
$types = array_merge(self::ITERABLE, array_diff($types, self::TRAVERSABLE_ARRAY));
}
return implode(
'|',
array_map(
static function (string $type): string {
return strpos($type, '&') === false ? $type : sprintf('(%s)', $type);
},
$types
)
);
}
throw new InvalidArgumentException('Unknown ReflectionType: ' . get_debug_type($type));
}
/**
* Get the string representation of the given type.
*
* @param \ReflectionType $type
* @param \ReflectionClass $declaringClass
*
* @return list<array{typeHint: string, isPrimitive: bool}>
* @return list<array{typeHint:string,isPrimitive:bool}>
*/
private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass)
private static function getTypeInformation(ReflectionType $type, ReflectionClass $declaringClass): array
{
// PHP 8 union types can be recursively processed
if ($type instanceof \ReflectionUnionType) {
// PHP 8 union types and PHP 8.1 intersection types can be recursively processed
if ($type instanceof ReflectionUnionType || $type instanceof ReflectionIntersectionType) {
$types = [];
foreach ($type->getTypes() as $innterType) {
@@ -172,7 +280,7 @@ class Reflector
return [
[
'typeHint' => $typeHint,
'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']),
'isPrimitive' => in_array($typeHint, self::BUILTIN_TYPES, true),
],
];
}
@@ -205,20 +313,4 @@ class Reflector
],
];
}
/**
* Format the given type as a nullable type.
*
* @param string $typeHint
*
* @return string
*/
private static function formatNullableType($typeHint)
{
if (\PHP_VERSION_ID < 80000) {
return sprintf('?%s', $typeHint);
}
return $typeHint === 'mixed' ? 'mixed' : sprintf('%s|null', $typeHint);
}
}

View File

@@ -1,32 +1,25 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
use function spl_object_hash;
class Undefined
{
/**
* Call capturing to merely return this same object.
*
* @param string $method
* @param array $args
* @param array $args
*
* @return self
*/
public function __call($method, array $args)
@@ -35,12 +28,12 @@ class Undefined
}
/**
* Return a string, avoiding E_RECOVERABLE_ERROR
* Return a string, avoiding E_RECOVERABLE_ERROR.
*
* @return string
*/
public function __toString()
{
return __CLASS__ . ":" . spl_object_hash($this);
return self::class . ':' . spl_object_hash($this);
}
}

View File

@@ -1,107 +1,168 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class VerificationDirector
{
private $receivedMethodCalls;
/**
* @var VerificationExpectation
*/
private $expectation;
/**
* @var ReceivedMethodCalls
*/
private $receivedMethodCalls;
public function __construct(ReceivedMethodCalls $receivedMethodCalls, VerificationExpectation $expectation)
{
$this->receivedMethodCalls = $receivedMethodCalls;
$this->expectation = $expectation;
}
public function verify()
{
return $this->receivedMethodCalls->verify($this->expectation);
}
public function with(...$args)
{
return $this->cloneApplyAndVerify("with", $args);
}
public function withArgs($args)
{
return $this->cloneApplyAndVerify("withArgs", array($args));
}
public function withNoArgs()
{
return $this->cloneApplyAndVerify("withNoArgs", array());
}
public function withAnyArgs()
{
return $this->cloneApplyAndVerify("withAnyArgs", array());
}
public function times($limit = null)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("times", array($limit));
}
public function once()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("once", array());
}
public function twice()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("twice", array());
}
/**
* @return self
*/
public function atLeast()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array());
return $this->cloneWithoutCountValidatorsApplyAndVerify('atLeast', []);
}
/**
* @return self
*/
public function atMost()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array());
return $this->cloneWithoutCountValidatorsApplyAndVerify('atMost', []);
}
/**
* @param int $minimum
* @param int $maximum
*
* @return self
*/
public function between($minimum, $maximum)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum));
return $this->cloneWithoutCountValidatorsApplyAndVerify('between', [$minimum, $maximum]);
}
protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
/**
* @return self
*/
public function once()
{
$expectation = clone $this->expectation;
$expectation->clearCountValidators();
call_user_func_array(array($expectation, $method), $args);
$director = new VerificationDirector($this->receivedMethodCalls, $expectation);
$director->verify();
return $director;
return $this->cloneWithoutCountValidatorsApplyAndVerify('once', []);
}
/**
* @param int $limit
*
* @return self
*/
public function times($limit = null)
{
return $this->cloneWithoutCountValidatorsApplyAndVerify('times', [$limit]);
}
/**
* @return self
*/
public function twice()
{
return $this->cloneWithoutCountValidatorsApplyAndVerify('twice', []);
}
public function verify()
{
$this->receivedMethodCalls->verify($this->expectation);
}
/**
* @template TArgs
*
* @param TArgs $args
*
* @return self
*/
public function with(...$args)
{
return $this->cloneApplyAndVerify('with', $args);
}
/**
* @return self
*/
public function withAnyArgs()
{
return $this->cloneApplyAndVerify('withAnyArgs', []);
}
/**
* @template TArgs
*
* @param TArgs $args
*
* @return self
*/
public function withArgs($args)
{
return $this->cloneApplyAndVerify('withArgs', [$args]);
}
/**
* @return self
*/
public function withNoArgs()
{
return $this->cloneApplyAndVerify('withNoArgs', []);
}
/**
* @param string $method
* @param array $args
*
* @return self
*/
protected function cloneApplyAndVerify($method, $args)
{
$expectation = clone $this->expectation;
call_user_func_array(array($expectation, $method), $args);
$director = new VerificationDirector($this->receivedMethodCalls, $expectation);
$director->verify();
return $director;
$verificationExpectation = clone $this->expectation;
$verificationExpectation->{$method}(...$args);
$verificationDirector = new self($this->receivedMethodCalls, $verificationExpectation);
$verificationDirector->verify();
return $verificationDirector;
}
/**
* @param string $method
* @param array $args
*
* @return self
*/
protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args)
{
$verificationExpectation = clone $this->expectation;
$verificationExpectation->clearCountValidators();
$verificationExpectation->{$method}(...$args);
$verificationDirector = new self($this->receivedMethodCalls, $verificationExpectation);
$verificationDirector->verify();
return $verificationDirector;
}
}

View File

@@ -1,35 +1,29 @@
<?php
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
namespace Mockery;
class VerificationExpectation extends Expectation
{
public function clearCountValidators()
{
$this->_countValidators = array();
}
public function __clone()
{
parent::__clone();
$this->_actualCount = 0;
}
/**
* @return void
*/
public function clearCountValidators()
{
$this->_countValidators = [];
}
}

View File

@@ -1,64 +1,76 @@
<?php
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\AnyArgs;
/**
* Mockery
* Mockery (https://docs.mockery.io/)
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/blob/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @copyright Copyright (c) 2016 Dave Marshall
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
* @copyright https://github.com/mockery/mockery/blob/HEAD/COPYRIGHT.md
* @license https://github.com/mockery/mockery/blob/HEAD/LICENSE BSD 3-Clause License
* @link https://github.com/mockery/mockery for the canonical source repository
*/
if (!function_exists("mock")) {
use Mockery\LegacyMockInterface;
use Mockery\Matcher\AndAnyOtherArgs;
use Mockery\Matcher\AnyArgs;
use Mockery\MockInterface;
if (! \function_exists('mock')) {
/**
* @template TMock of object
*
* @param array<class-string<TMock>|TMock|Closure(LegacyMockInterface&MockInterface&TMock):LegacyMockInterface&MockInterface&TMock|array<TMock>> $args
*
* @return LegacyMockInterface&MockInterface&TMock
*/
function mock(...$args)
{
return Mockery::mock(...$args);
}
}
if (!function_exists("spy")) {
if (! \function_exists('spy')) {
/**
* @template TSpy of object
*
* @param array<class-string<TSpy>|TSpy|Closure(LegacyMockInterface&MockInterface&TSpy):LegacyMockInterface&MockInterface&TSpy|array<TSpy>> $args
*
* @return LegacyMockInterface&MockInterface&TSpy
*/
function spy(...$args)
{
return Mockery::spy(...$args);
}
}
if (!function_exists("namedMock")) {
if (! \function_exists('namedMock')) {
/**
* @template TNamedMock of object
*
* @param array<class-string<TNamedMock>|TNamedMock|array<TNamedMock>> $args
*
* @return LegacyMockInterface&MockInterface&TNamedMock
*/
function namedMock(...$args)
{
return Mockery::namedMock(...$args);
}
}
if (!function_exists("anyArgs")) {
function anyArgs()
if (! \function_exists('anyArgs')) {
function anyArgs(): AnyArgs
{
return new AnyArgs();
}
}
if (!function_exists("andAnyOtherArgs")) {
function andAnyOtherArgs()
if (! \function_exists('andAnyOtherArgs')) {
function andAnyOtherArgs(): AndAnyOtherArgs
{
return new AndAnyOtherArgs();
}
}
if (!function_exists("andAnyOthers")) {
function andAnyOthers()
if (! \function_exists('andAnyOthers')) {
function andAnyOthers(): AndAnyOtherArgs
{
return new AndAnyOtherArgs();
}