laravel-6 support

This commit is contained in:
RafficMohammed
2023-01-08 01:17:22 +05:30
parent 1a5c16ae4b
commit 774eed8b0e
4962 changed files with 279380 additions and 297961 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

@@ -3,17 +3,65 @@
## 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
## 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
## 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
## 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
## 1.3.4 (2021-02-24)
* 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)
## 1.4.1 (2020-07-09)
* 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)
## 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)
@@ -21,12 +69,20 @@
* 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)
## 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)
## 1.3.1 (2019-12-26)
* Revert improved exception debugging due to BC breaks (#1032)
## 1.3.0 (2019-11-24)

View File

@@ -1,7 +1,7 @@
Mockery
=======
[![Build Status](https://github.com/mockery/mockery/workflows/tests/badge.svg)](https://github.com/mockery/mockery/actions)
[![Build Status](https://github.com/mockery/mockery/actions/workflows/tests.yml/badge.svg)](https://github.com/mockery/mockery/actions)
[![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)
@@ -33,6 +33,14 @@ to learn how to use Mockery.
The current version can be seen at [docs.mockery.io](http://docs.mockery.io).
## PHPUnit Integration
Mockery ships with some helpers if you are using PHPUnit. You can extend the
[`Mockery\Adapter\Phpunit\MockeryTestCase`](library/Mockery/Adapter/Phpunit/MockeryTestCase.php)
class instead of `PHPUnit\Framework\TestCase`, or if you are already using a
custom base class for your tests, take a look at the traits available in the
[`Mockery\Adapter\Phpunit`](library/Mockery/Adapter/Phpunit) namespace.
## Test Doubles
Test doubles (often called mocks) simulate the behaviour of real objects. They are
@@ -267,7 +275,7 @@ versioning scheme.
### Alternative Runtimes
Mockery will attempt to continue support HHVM, but will not make any guarantees.
Mockery 1.3 was the last version to support HHVM 3 and PHP 5. There is no support for HHVM 4+.
## A new home for Mockery

View File

@@ -31,12 +31,15 @@
}
],
"require": {
"php": ">=5.6.0",
"php": "^7.3 || ^8.0",
"lib-pcre": ">=7.0",
"hamcrest/hamcrest-php": "^2.0.1"
},
"require-dev": {
"phpunit/phpunit": "^5.7.10|^6.5|^7.5|^8.5|^9.3"
"phpunit/phpunit": "^8.5 || ^9.3"
},
"conflict": {
"phpunit/phpunit": "<8.0"
},
"autoload": {
"psr-0": {
@@ -53,7 +56,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
"dev-master": "1.4.x-dev"
}
}
}

View File

@@ -5,13 +5,15 @@ Mockery Global Configuration
============================
To allow for a degree of fine-tuning, Mockery utilises a singleton
configuration object to store a small subset of core behaviours. The two
configuration object to store a small subset of core behaviours. The three
currently present include:
* Option to allow/disallow the mocking of methods which do not actually exist
fulfilled (i.e. unused)
* Setter/Getter for added a parameter map for internal PHP class methods
(``Reflection`` cannot detect these automatically)
* Option to drive if quick definitions should define a stub or a mock with
an 'at least once' expectation.
By default, the first behaviour is enabled. Of course, there are
situations where this can lead to unintended consequences. The mocking of
@@ -49,6 +51,19 @@ won't correctly add it automatically for internal classes. Note that internal cl
parameter overriding is not available in PHP 8. This is because incompatible
signatures have been reclassified as fatal errors.
Finally there is the possibility to change what a quick definition produces.
By default quick definitions create stubs but you can change this behaviour
by asking Mockery to use 'at least once' expectations.
.. code-block:: php
\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce(bool)
Passing a true allows the behaviour, false disallows it. It takes effect
immediately until switched back. By doing so you can avoid the proliferating of
quick definitions that accumulate overtime in your code since the test would
fail in case the 'at least once' expectation is not fulfilled.
Disabling reflection caching
----------------------------

View File

@@ -12,7 +12,20 @@ name collision (reported as a PHP fatal error). The methods reserved by
Mockery are:
* ``shouldReceive()``
* ``shouldBeStrict()``
* ``shouldNotReceive()``
* ``allows()``
* ``expects()``
* ``shouldAllowMockingMethod()``
* ``shouldIgnoreMissing()``
* ``asUndefined()``
* ``shouldAllowMockingProtectedMethods()``
* ``makePartial()``
* ``byDefault()``
* ``shouldHaveReceived()``
* ``shouldHaveBeenCalled()``
* ``shouldNotHaveReceived()``
* ``shouldNotHaveBeenCalled()``
In addition, all mocks utilise a set of added methods and protected properties
which cannot exist on the class or object being mocked. These are far less

View File

@@ -212,7 +212,7 @@ the ``\Mockery::pattern()``:
// Hamcrest equivalent
$mock->shouldReceive('foo')
with(matchesPattern('/^foo/'));
->with(matchesPattern('/^foo/'));
The ``ducktype()`` matcher is an alternative to matching by class type:

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,9 +9,10 @@ classes or methods marked final is hard. The final keyword prevents methods so
marked from being replaced in subclasses (subclassing is how mock objects can
inherit the type of the class or object being mocked).
The simplest solution is to not mark classes or methods as final!
The simplest solution is to implement an interface in your final class and
typehint against / mock this.
However, in a compromise between mocking functionality and type safety,
However this may not be possible in some third party libraries.
Mockery does allow creating "proxy mocks" from classes marked final, or from
classes with methods marked final. This offers all the usual mock object
goodness but the resulting mock will not inherit the class type of the object

View File

@@ -114,12 +114,6 @@ Make sure Composer's or Mockery's autoloader is present in the bootstrap file
or we will need to also define a "file" attribute pointing to the file of the
``TestListener`` class.
.. caution::
The ``TestListener`` will only work for PHPUnit 6+ versions.
For PHPUnit versions 5 and lower, the test listener does not work.
If we are creating the test suite programmatically we may add the listener
like this:

View File

@@ -17,7 +17,7 @@ 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
we have to tell our mocks what to expect before we act on the SUT, then assert
that those expectations where met:
.. code-block:: php

View File

@@ -80,24 +80,18 @@ class Mockery
*/
public static function builtInTypes()
{
$builtInTypes = array(
'self',
return array(
'array',
'callable',
// Up to php 7
'bool',
'callable',
'float',
'int',
'string',
'iterable',
'object',
'self',
'string',
'void',
);
if (\PHP_VERSION_ID >= 70200) {
$builtInTypes[] = 'object';
}
return $builtInTypes;
}
/**
@@ -404,7 +398,7 @@ class Mockery
/**
* Return instance of CONTAINS matcher.
*
* @param array ...$args
* @param mixed $args
*
* @return \Mockery\Matcher\Contains
*/
@@ -668,10 +662,22 @@ class Mockery
return array('...');
}
return array(
'class' => get_class($object),
'properties' => self::extractInstancePublicProperties($object, $nesting)
$defaultFormatter = function ($object, $nesting) {
return array('properties' => self::extractInstancePublicProperties($object, $nesting));
};
$class = get_class($object);
$formatter = self::getConfiguration()->getObjectFormatter($class, $defaultFormatter);
$array = array(
'class' => $class,
'identity' => '#' . md5(spl_object_hash($object))
);
$array = array_merge($array, $formatter($object, $nesting));
return $array;
}
/**
@@ -691,7 +697,11 @@ class Mockery
foreach ($properties as $publicProperty) {
if (!$publicProperty->isStatic()) {
$name = $publicProperty->getName();
$cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
try {
$cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
} catch (\Exception $exception) {
$cleanedProperties[$name] = $exception->getMessage();
}
}
}
@@ -863,28 +873,26 @@ class Mockery
) {
$newMockName = 'demeter_' . md5($parent) . '_' . $method;
if (\PHP_VERSION_ID >= 70000) {
$parRef = null;
$parRefMethod = null;
$parRefMethodRetType = null;
$parRef = null;
$parRefMethod = null;
$parRefMethodRetType = null;
$parentMock = $exp->getMock();
if ($parentMock !== null) {
$parRef = new ReflectionObject($parentMock);
}
$parentMock = $exp->getMock();
if ($parentMock !== null) {
$parRef = new ReflectionObject($parentMock);
}
if ($parRef !== null && $parRef->hasMethod($method)) {
$parRefMethod = $parRef->getMethod($method);
$parRefMethodRetType = Reflector::getReturnType($parRefMethod, true);
if ($parRef !== null && $parRef->hasMethod($method)) {
$parRefMethod = $parRef->getMethod($method);
$parRefMethodRetType = Reflector::getReturnType($parRefMethod, true);
if ($parRefMethodRetType !== null) {
$nameBuilder = new MockNameBuilder();
$nameBuilder->addPart('\\' . $newMockName);
$mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType);
$exp->andReturn($mock);
if ($parRefMethodRetType !== null && $parRefMethodRetType !== 'mixed') {
$nameBuilder = new MockNameBuilder();
$nameBuilder->addPart('\\' . $newMockName);
$mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType);
$exp->andReturn($mock);
return $mock;
}
return $mock;
}
}

View File

@@ -1,47 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Adapter\Phpunit\Legacy;
class TestListenerForV5 extends \PHPUnit_Framework_BaseTestListener
{
private $trait;
public function __construct()
{
$this->trait = new TestListenerTrait();
}
/**
* {@inheritdoc}
*/
public function endTest(\PHPUnit_Framework_Test $test, $time)
{
$this->trait->endTest($test, $time);
}
/**
* {@inheritdoc}
*/
public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
{
$this->trait->startTestSuite();
}
}

View File

@@ -1,51 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Adapter\Phpunit\Legacy;
use PHPUnit\Framework\BaseTestListener;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestSuite;
class TestListenerForV6 extends BaseTestListener
{
private $trait;
public function __construct()
{
$this->trait = new TestListenerTrait();
}
/**
* {@inheritdoc}
*/
public function endTest(Test $test, $time)
{
$this->trait->endTest($test, $time);
}
/**
* {@inheritdoc}
*/
public function startTestSuite(TestSuite $suite)
{
$this->trait->startTestSuite();
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Adapter\Phpunit\Legacy;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
class TestListenerForV7 implements TestListener
{
use TestListenerDefaultImplementation;
private $trait;
public function __construct()
{
$this->trait = new TestListenerTrait();
}
/**
* {@inheritdoc}
*/
public function endTest(Test $test, float $time): void
{
$this->trait->endTest($test, $time);
}
/**
* {@inheritdoc}
*/
public function startTestSuite(TestSuite $suite): void
{
$this->trait->startTestSuite();
}
}

View File

@@ -22,12 +22,6 @@ namespace Mockery\Adapter\Phpunit;
use Mockery;
if (class_exists('PHPUnit_Framework_TestCase') || version_compare(\PHPUnit\Runner\Version::id(), '8.0.0', '<')) {
class_alias(MockeryPHPUnitIntegrationAssertPostConditionsForV7AndPrevious::class, MockeryPHPUnitIntegrationAssertPostConditions::class);
} else {
class_alias(MockeryPHPUnitIntegrationAssertPostConditionsForV8::class, MockeryPHPUnitIntegrationAssertPostConditions::class);
}
/**
* Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
* for each test and are included by the assertion counter.

View File

@@ -22,7 +22,7 @@ declare(strict_types=1);
namespace Mockery\Adapter\Phpunit;
trait MockeryPHPUnitIntegrationAssertPostConditionsForV8
trait MockeryPHPUnitIntegrationAssertPostConditions
{
protected function assertPostConditions(): void
{

View File

@@ -1,29 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Adapter\Phpunit;
trait MockeryPHPUnitIntegrationAssertPostConditionsForV7AndPrevious
{
protected function assertPostConditions()
{
$this->mockeryAssertPostConditions();
}
}

View File

@@ -20,11 +20,6 @@
namespace Mockery\Adapter\Phpunit;
if (class_exists('PHPUnit_Framework_TestCase') || version_compare(\PHPUnit\Runner\Version::id(), '8.0.0', '<')) {
class_alias(MockeryTestCaseSetUpForV7AndPrevious::class, MockeryTestCaseSetUp::class);
} else {
class_alias(MockeryTestCaseSetUpForV8::class, MockeryTestCaseSetUp::class);
}
abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
{
use MockeryPHPUnitIntegration;
@@ -37,22 +32,4 @@ abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
protected function mockeryTestTearDown()
{
}
public function expectExceptionMessageRegEx($regularExpression)
{
if (method_exists(get_parent_class(), 'expectExceptionMessageRegExp')) {
return parent::expectExceptionMessageRegExp($regularExpression);
}
return $this->expectExceptionMessageMatches($regularExpression);
}
public static function assertMatchesRegEx($pattern, $string, $message = '')
{
if (method_exists(get_parent_class(), 'assertMatchesRegularExpression')) {
parent::assertMatchesRegularExpression($pattern, $string, $message);
}
self::assertRegExp($pattern, $string, $message);
}
}

View File

@@ -22,7 +22,7 @@ declare(strict_types=1);
namespace Mockery\Adapter\Phpunit;
trait MockeryTestCaseSetUpForV8
trait MockeryTestCaseSetUp
{
protected function setUp(): void
{

View File

@@ -1,36 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Adapter\Phpunit;
trait MockeryTestCaseSetUpForV7AndPrevious
{
protected function setUp()
{
parent::setUp();
$this->mockeryTestSetUp();
}
protected function tearDown()
{
$this->mockeryTestTearDown();
parent::tearDown();
}
}

View File

@@ -20,16 +20,29 @@
namespace Mockery\Adapter\Phpunit;
if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) {
class_alias('Mockery\Adapter\Phpunit\Legacy\TestListenerForV5', 'Mockery\Adapter\Phpunit\TestListener');
} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) {
class_alias('Mockery\Adapter\Phpunit\Legacy\TestListenerForV6', 'Mockery\Adapter\Phpunit\TestListener');
} else {
class_alias('Mockery\Adapter\Phpunit\Legacy\TestListenerForV7', 'Mockery\Adapter\Phpunit\TestListener');
}
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
if (false) {
class TestListener
class TestListener implements PHPUnitTestListener
{
use TestListenerDefaultImplementation;
private $trait;
public function __construct()
{
$this->trait = new TestListenerTrait();
}
public function endTest(Test $test, float $time): void
{
$this->trait->endTest($test, $time);
}
public function startTestSuite(TestSuite $suite): void
{
$this->trait->startTestSuite();
}
}

View File

@@ -18,15 +18,7 @@
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/
namespace Mockery\Adapter\Phpunit\Legacy;
if (class_exists('PHPUnit_Framework_TestCase') && ! class_exists('PHPUnit\Util\Blacklist')) {
class_alias('PHPUnit_Framework_ExpectationFailedException', 'PHPUnit\Framework\ExpectationFailedException');
class_alias('PHPUnit_Framework_Test', 'PHPUnit\Framework\Test');
class_alias('PHPUnit_Framework_TestCase', 'PHPUnit\Framework\TestCase');
class_alias('PHPUnit_Util_Blacklist', 'PHPUnit\Util\Blacklist');
class_alias('PHPUnit_Runner_BaseTestRunner', 'PHPUnit\Runner\BaseTestRunner');
}
namespace Mockery\Adapter\Phpunit;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\Test;

View File

@@ -40,6 +40,11 @@ class Configuration
*/
protected $_allowMockingMethodsUnnecessarily = true;
/**
* @var QuickDefinitionsConfiguration
*/
protected $_quickDefinitionsConfiguration;
/**
* Parameter map for use with PHP internal classes.
*
@@ -57,6 +62,25 @@ class Configuration
*/
protected $_reflectionCacheEnabled = true;
public function __construct()
{
$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
*
@@ -78,15 +102,15 @@ class Configuration
}
/**
* @deprecated
*
* Set boolean to allow/prevent unnecessary mocking of methods
*
* @param bool $flag
*
* @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;
}
@@ -95,10 +119,12 @@ class Configuration
* 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);
@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;
}
@@ -158,6 +184,14 @@ class Configuration
return $this->_constantsMap;
}
/**
* Returns the quick definitions configuration
*/
public function getQuickDefinitions(): QuickDefinitionsConfiguration
{
return $this->_quickDefinitionsConfiguration;
}
/**
* Disable reflection caching
*
@@ -191,4 +225,59 @@ class Configuration
{
return $this->_reflectionCacheEnabled;
}
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

@@ -190,12 +190,6 @@ class Container
$builder->addBlackListedMethods($blocks);
if (defined('HHVM_VERSION')
&& ($class === 'Exception' || is_subclass_of($class, 'Exception'))) {
$builder->addBlackListedMethod("setTraceOptions");
$builder->addBlackListedMethod("getTraceOptions");
}
if (!is_null($constructorArgs)) {
$builder->addBlackListedMethod("__construct"); // we need to pass through
} else {
@@ -225,7 +219,11 @@ class Container
$mock->mockery_init($this, $config->getTargetObject(), $config->isInstanceMock());
if (!empty($quickdefs)) {
$mock->shouldReceive($quickdefs)->byDefault();
if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) {
$mock->shouldReceive($quickdefs)->atLeast()->once();
} else {
$mock->shouldReceive($quickdefs)->byDefault();
}
}
if (!empty($expectationClosure)) {
$expectationClosure($mock);

View File

@@ -194,7 +194,7 @@ class Expectation implements ExpectationInterface
/**
* Throws an exception if the expectation has been configured to do so
*
* @throws \Exception|\Throwable
* @throws \Throwable
* @return void
*/
private function throwAsNecessary($return)
@@ -203,9 +203,7 @@ class Expectation implements ExpectationInterface
return;
}
$type = \PHP_VERSION_ID >= 70000 ? "\Throwable" : "\Exception";
if ($return instanceof $type) {
if ($return instanceof \Throwable) {
throw $return;
}
@@ -391,6 +389,12 @@ class Expectation implements ExpectationInterface
return true;
}
}
if (is_object($expected)) {
$matcher = \Mockery::getConfiguration()->getDefaultMatcher(get_class($expected));
if ($matcher !== null) {
$expected = new $matcher($expected);
}
}
if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
return $expected->match($actual);
}
@@ -567,7 +571,7 @@ class Expectation implements ExpectationInterface
public function andReturnArg($index)
{
if (!is_int($index) || $index < 0) {
throw new \InvalidArgumentException("Invalid argument index supplied. Index must be a positive integer.");
throw new \InvalidArgumentException("Invalid argument index supplied. Index must be a non-negative integer.");
}
$closure = function (...$args) use ($index) {
if (array_key_exists($index, $args)) {
@@ -666,6 +670,25 @@ class Expectation implements ExpectationInterface
return $this;
}
/**
* Sets up a closure that will yield each of the provided args
*
* @param mixed ...$args
* @return self
*/
public function andYield(...$args)
{
$this->_closureQueue = [
static function () use ($args) {
foreach ($args as $arg) {
yield $arg;
}
},
];
return $this;
}
/**
* Alias to andSet(). Allows the natural English construct
* - set('foo', 'bar')->andReturn('bar')
@@ -705,7 +728,12 @@ class Expectation implements ExpectationInterface
throw new \InvalidArgumentException('The passed Times limit should be an integer value');
}
$this->_countValidators[$this->_countValidatorClass] = new $this->_countValidatorClass($this, $limit);
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
if ('Mockery\CountValidator\Exact' !== $this->_countValidatorClass) {
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
unset($this->_countValidators[$this->_countValidatorClass]);
}
return $this;
}

View File

@@ -213,6 +213,14 @@ class ExpectationDirector
*/
public function getExpectationCount()
{
return count($this->getExpectations()) ?: count($this->getDefaultExpectations());
$count = 0;
/** @var Expectation $expectations */
$expectations = $this->getExpectations() ?: $this->getDefaultExpectations();
foreach ($expectations as $expectation) {
if ($expectation->isCallCountConstrained()) {
$count++;
}
}
return $count;
}
}

View File

@@ -34,7 +34,7 @@ interface ExpectationInterface
public function getMock();
/**
* @param array ...$args
* @param mixed $args
* @return self
*/
public function andReturn(...$args);

View File

@@ -526,34 +526,6 @@ class MockConfiguration
return true;
});
// In HHVM, class methods can be annotated with the built-in
// <<__Memoize>> attribute (similar to a Python decorator),
// which builds an LRU cache of method arguments and their
// return values.
// https://docs.hhvm.com/hack/attributes/special#__memoize
//
// HHVM implements this behavior by inserting a private helper
// method into the class at runtime which is named as the
// method to be memoized, suffixed by `$memoize_impl`.
// https://github.com/facebook/hhvm/blob/6aa46f1e8c2351b97d65e67b73e26f274a7c3f2e/hphp/runtime/vm/func.cpp#L364
//
// Ordinarily, PHP does not all allow the `$` token in method
// names, but since the memoization helper is inserted at
// runtime (and not in userland), HHVM allows it.
//
// We use code generation and eval() for some types of mocks,
// so to avoid syntax errors from these memoization helpers,
// we must filter them from our list of class methods.
//
// This effectively disables the memoization behavior in HHVM,
// but that's preferable to failing catastrophically when
// attempting to mock a class using the attribute.
if (defined('HHVM_VERSION')) {
$methods = array_filter($methods, function ($method) {
return strpos($method->getName(), '$memoize_impl') === false;
});
}
return $this->allMethods = $methods;
}

View File

@@ -72,9 +72,7 @@ class MockConfigurationBuilder
public function __construct()
{
if (\PHP_VERSION_ID >= 70000) {
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
}
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
}
public function addTarget($target)

View File

@@ -37,11 +37,6 @@ class ClassPass implements Pass
}
$className = ltrim($target->getName(), "\\");
if (defined('HHVM_VERSION') && preg_match('/^HH\\\\/', $className)) {
// HH\ namespace is reserved for HHVM class and doesnt require
// class declaration and extension.
return $code;
}
if (!class_exists($className)) {
\Mockery::declareClass($className);

View File

@@ -75,7 +75,8 @@ class MethodDefinitionPass implements Pass
if (!$param->isVariadic()) {
if (false !== $param->isDefaultValueAvailable()) {
$paramDef .= ' = ' . var_export($param->getDefaultValue(), true);
$defaultValue = $param->getDefaultValue();
$paramDef .= ' = ' . (is_object($defaultValue) ? get_class($defaultValue) : var_export($defaultValue, true));
} elseif ($param->isOptional()) {
$paramDef .= ' = null';
}
@@ -156,7 +157,7 @@ BODY;
$body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n";
if ($method->getReturnType() !== "void") {
if (! in_array($method->getReturnType(), ['never','void'], true)) {
$body .= "return \$ret;\n";
}

View File

@@ -32,6 +32,7 @@ class RemoveBuiltinMethodsThatAreFinalPass
{
protected $methods = array(
'__wakeup' => '/public function __wakeup\(\)\s+\{.*?\}/sm',
'__toString' => '/public function __toString\(\)\s+(:\s+string)?\s*\{.*?\}/sm',
);
public function apply($code, MockConfiguration $config)

View File

@@ -69,7 +69,7 @@ interface LegacyMockInterface
/**
* Set mock to defer unexpected methods to its parent if possible
*
* @deprecated 2.0.0 Please use makePartial() instead
* @deprecated since 1.4.0. Please use makePartial() instead.
*
* @return Mock
*/

View File

@@ -1,76 +0,0 @@
<?php
/**
* Mockery
*
* 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
*/
namespace Mockery\Matcher;
use Mockery\Exception\InvalidArgumentException;
class PHPUnitConstraint extends MatcherAbstract
{
protected $constraint;
protected $rethrow;
/**
* @param mixed $constraint
* @param bool $rethrow
*/
public function __construct($constraint, $rethrow = false)
{
if (!($constraint instanceof \PHPUnit_Framework_Constraint)
&& !($constraint instanceof \PHPUnit\Framework\Constraint)) {
throw new InvalidArgumentException(
'Constraint must be one of \PHPUnit\Framework\Constraint or ' .
'\PHPUnit_Framework_Constraint'
);
}
$this->constraint = $constraint;
$this->rethrow = $rethrow;
}
/**
* @param mixed $actual
* @return bool
*/
public function match(&$actual)
{
try {
$this->constraint->evaluate($actual);
return true;
} catch (\PHPUnit_Framework_AssertionFailedError $e) {
if ($this->rethrow) {
throw $e;
}
return false;
} catch (\PHPUnit\Framework\AssertionFailedError $e) {
if ($this->rethrow) {
throw $e;
}
return false;
}
}
/**
*
*/
public function __toString()
{
return '<Constraint>';
}
}

View File

@@ -52,6 +52,14 @@ class Mock implements MockInterface
*/
protected $_mockery_ignoreMissing = false;
/**
* Flag to indicate whether we want to set the ignoreMissing flag on
* mocks generated form this calls to this one
*
* @var bool
*/
protected $_mockery_ignoreMissingRecursive = false;
/**
* Flag to indicate whether we can defer method calls missing from our
* expectations
@@ -308,11 +316,13 @@ 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
*/
public function shouldIgnoreMissing($returnValue = null)
public function shouldIgnoreMissing($returnValue = null, $recursive = false)
{
$this->_mockery_ignoreMissing = true;
$this->_mockery_ignoreMissingRecursive = $recursive;
$this->_mockery_defaultReturnValue = $returnValue;
return $this;
}
@@ -657,9 +667,9 @@ class Mock implements MockInterface
{
$rfc = new \ReflectionClass($this);
// HHVM has a Stringish interface and PHP 8 has Stringable
// PHP 8 has Stringable interface
$interfaces = array_filter($rfc->getInterfaces(), function ($i) {
return $i->getName() !== 'Stringish' && $i->getName() !== 'Stringable';
return $i->getName() !== 'Stringable';
});
return false === $rfc->getParentClass() && 2 === count($interfaces);
@@ -737,11 +747,22 @@ class Mock implements MockInterface
case 'void':
return null;
case 'static':
return $this;
case 'object':
return \Mockery::mock();
$mock = \Mockery::mock();
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
default:
return \Mockery::mock($returnType);
$mock = \Mockery::mock($returnType);
if ($this->_mockery_ignoreMissingRecursive) {
$mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true);
}
return $mock;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* Mockery
*
* 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
*/
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';
/**
* Defines what a quick definition should produce.
* Possible options are:
* - self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION: in this case quick
* definitions define a stub.
* - self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE: in this case quick
* definitions define a mock with an 'at least once' expectation.
*
* @var string
*/
protected $_quickDefinitionsApplicationMode = self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION;
/**
* Returns true if quick definitions should setup a stub, returns false when
* quick definitions should setup a mock with 'at least once' expectation.
* When parameter $newValue is specified it sets the configuration with the
* given value.
*/
public function shouldBeCalledAtLeastOnce(?bool $newValue = null): bool
{
if ($newValue !== null) {
$this->_quickDefinitionsApplicationMode = $newValue
? self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE
: self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION;
}
return $this->_quickDefinitionsApplicationMode === self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE;
}
}

View File

@@ -35,13 +35,9 @@ class Reflector
*/
public static function isArray(\ReflectionParameter $param)
{
if (\PHP_VERSION_ID < 70100) {
return $param->isArray();
}
$type = $param->getType();
return $type instanceof \ReflectionNamedType ? $type->getName() === 'array' : false;
return $type instanceof \ReflectionNamedType && $type->getName();
}
/**
@@ -54,13 +50,6 @@ class Reflector
*/
public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false)
{
// returns false if we are running PHP 7+
$typeHint = self::getLegacyTypeHint($param);
if ($typeHint !== false) {
return $typeHint;
}
if (!$param->hasType()) {
return null;
}
@@ -69,8 +58,7 @@ class Reflector
$declaringClass = $param->getDeclaringClass();
$typeHint = self::typeToString($type, $declaringClass);
// PHP 7.1+ supports nullable types via a leading question mark
return (!$withoutNullable && \PHP_VERSION_ID >= 70100 && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
@@ -83,11 +71,6 @@ class Reflector
*/
public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false)
{
// Strip all return types for HHVM and skip PHP 5.
if (method_exists($method, 'getReturnTypeText') || \PHP_VERSION_ID < 70000) {
return null;
}
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
@@ -100,8 +83,7 @@ class Reflector
$typeHint = self::typeToString($type, $method->getDeclaringClass());
// PHP 7.1+ supports nullable types via a leading question mark
return (!$withoutNullable && \PHP_VERSION_ID >= 70100 && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint;
}
/**
@@ -113,11 +95,6 @@ class Reflector
*/
public static function getSimplestReturnType(\ReflectionMethod $method)
{
// Strip all return types for HHVM and skip PHP 5.
if (method_exists($method, 'getReturnTypeText') || \PHP_VERSION_ID < 70000) {
return null;
}
$type = $method->getReturnType();
if (is_null($type) && method_exists($method, 'getTentativeReturnType')) {
@@ -145,95 +122,11 @@ class Reflector
return null;
}
/**
* Compute the legacy type hint.
*
* We return:
* - string: the legacy type hint
* - null: if there is no legacy type hint
* - false: if we must check for PHP 7+ typing
*
* @param \ReflectionParameter $param
*
* @return string|null|false
*/
private static function getLegacyTypeHint(\ReflectionParameter $param)
{
// Handle HHVM typing
if (\method_exists($param, 'getTypehintText')) {
if ($param->isArray()) {
return 'array';
}
if ($param->isCallable()) {
return 'callable';
}
$typeHint = $param->getTypehintText();
// throw away HHVM scalar types
if (\in_array($typeHint, array('int', 'integer', 'float', 'string', 'bool', 'boolean'), true)) {
return null;
}
return sprintf('\\%s', $typeHint);
}
// Handle PHP 5 typing
if (\PHP_VERSION_ID < 70000) {
if ($param->isArray()) {
return 'array';
}
if ($param->isCallable()) {
return 'callable';
}
$typeHint = self::getLegacyClassName($param);
return $typeHint === null ? null : sprintf('\\%s', $typeHint);
}
return false;
}
/**
* Compute the class name using legacy APIs, if possible.
*
* This method MUST only be called on PHP 5.
*
* @param \ReflectionParameter $param
*
* @return string|null
*/
private static function getLegacyClassName(\ReflectionParameter $param)
{
try {
$class = $param->getClass();
$typeHint = $class === null ? null : $class->getName();
} catch (\ReflectionException $e) {
$typeHint = null;
}
if ($typeHint === null) {
if (preg_match('/^Parameter #[0-9]+ \[ \<(required|optional)\> (?<typehint>\S+ )?.*\$' . $param->getName() . ' .*\]$/', (string) $param, $typehintMatch)) {
if (!empty($typehintMatch['typehint']) && $typehintMatch['typehint']) {
$typeHint = $typehintMatch['typehint'];
}
}
}
return $typeHint;
}
/**
* Get the string representation of the given type.
*
* This method MUST only be called on PHP 7+.
*
* @param \ReflectionType $type
* @param \ReflectionClass $declaringClass
* @param \ReflectionType $type
* @param string $declaringClass
*
* @return string|null
*/
@@ -247,8 +140,6 @@ class Reflector
/**
* Get the string representation of the given type.
*
* This method MUST only be called on PHP 7+.
*
* @param \ReflectionType $type
* @param \ReflectionClass $declaringClass
*
@@ -256,8 +147,8 @@ class Reflector
*/
private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass)
{
// 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) {
@@ -273,8 +164,8 @@ class Reflector
return $types;
}
// PHP 7.0 doesn't have named types, but 7.1+ does
$typeHint = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
// $type must be an instance of \ReflectionNamedType
$typeHint = $type->getName();
// builtins can be returned as is
if ($type->isBuiltin()) {
@@ -318,8 +209,6 @@ class Reflector
/**
* Format the given type as a nullable type.
*
* This method MUST only be called on PHP 7.1+.
*
* @param string $typeHint
*
* @return string