Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! rūx: x: README.mdnu ÕIw¶“ # Prophecy
[](https://packagist.org/packages/phpspec/prophecy)
[](https://travis-ci.org/phpspec/prophecy)
Prophecy is a highly opinionated yet very powerful and flexible PHP object mocking
framework. Though initially it was created to fulfil phpspec2 needs, it is flexible
enough to be used inside any testing framework out there with minimal effort.
## A simple example
```php
prophet->prophesize('App\Security\Hasher');
$user = new App\Entity\User($hasher->reveal());
$hasher->generateHash($user, 'qwerty')->willReturn('hashed_pass');
$user->setPassword('qwerty');
$this->assertEquals('hashed_pass', $user->getPassword());
}
protected function setUp()
{
$this->prophet = new \Prophecy\Prophet;
}
protected function tearDown()
{
$this->prophet->checkPredictions();
}
}
```
## Installation
### Prerequisites
Prophecy requires PHP 5.3.3 or greater.
### Setup through composer
First, add Prophecy to the list of dependencies inside your `composer.json`:
```json
{
"require-dev": {
"phpspec/prophecy": "~1.0"
}
}
```
Then simply install it with composer:
```bash
$> composer install --prefer-dist
```
You can read more about Composer on its [official webpage](http://getcomposer.org).
## How to use it
First of all, in Prophecy every word has a logical meaning, even the name of the library
itself (Prophecy). When you start feeling that, you'll become very fluid with this
tool.
For example, Prophecy has been named that way because it concentrates on describing the future
behavior of objects with very limited knowledge about them. But as with any other prophecy,
those object prophecies can't create themselves - there should be a Prophet:
```php
$prophet = new Prophecy\Prophet;
```
The Prophet creates prophecies by *prophesizing* them:
```php
$prophecy = $prophet->prophesize();
```
The result of the `prophesize()` method call is a new object of class `ObjectProphecy`. Yes,
that's your specific object prophecy, which describes how your object would behave
in the near future. But first, you need to specify which object you're talking about,
right?
```php
$prophecy->willExtend('stdClass');
$prophecy->willImplement('SessionHandlerInterface');
```
There are 2 interesting calls - `willExtend` and `willImplement`. The first one tells
object prophecy that our object should extend specific class, the second one says that
it should implement some interface. Obviously, objects in PHP can implement multiple
interfaces, but extend only one parent class.
### Dummies
Ok, now we have our object prophecy. What can we do with it? First of all, we can get
our object *dummy* by revealing its prophecy:
```php
$dummy = $prophecy->reveal();
```
The `$dummy` variable now holds a special dummy object. Dummy objects are objects that extend
and/or implement preset classes/interfaces by overriding all their public methods. The key
point about dummies is that they do not hold any logic - they just do nothing. Any method
of the dummy will always return `null` and the dummy will never throw any exceptions.
Dummy is your friend if you don't care about the actual behavior of this double and just need
a token object to satisfy a method typehint.
You need to understand one thing - a dummy is not a prophecy. Your object prophecy is still
assigned to `$prophecy` variable and in order to manipulate with your expectations, you
should work with it. `$dummy` is a dummy - a simple php object that tries to fulfil your
prophecy.
### Stubs
Ok, now we know how to create basic prophecies and reveal dummies from them. That's
awesome if we don't care about our _doubles_ (objects that reflect originals)
interactions. If we do, we need to use *stubs* or *mocks*.
A stub is an object double, which doesn't have any expectations about the object behavior,
but when put in specific environment, behaves in specific way. Ok, I know, it's cryptic,
but bear with me for a minute. Simply put, a stub is a dummy, which depending on the called
method signature does different things (has logic). To create stubs in Prophecy:
```php
$prophecy->read('123')->willReturn('value');
```
Oh wow. We've just made an arbitrary call on the object prophecy? Yes, we did. And this
call returned us a new object instance of class `MethodProphecy`. Yep, that's a specific
method with arguments prophecy. Method prophecies give you the ability to create method
promises or predictions. We'll talk about method predictions later in the _Mocks_ section.
#### Promises
Promises are logical blocks, that represent your fictional methods in prophecy terms
and they are handled by the `MethodProphecy::will(PromiseInterface $promise)` method.
As a matter of fact, the call that we made earlier (`willReturn('value')`) is a simple
shortcut to:
```php
$prophecy->read('123')->will(new Prophecy\Promise\ReturnPromise(array('value')));
```
This promise will cause any call to our double's `read()` method with exactly one
argument - `'123'` to always return `'value'`. But that's only for this
promise, there's plenty others you can use:
- `ReturnPromise` or `->willReturn(1)` - returns a value from a method call
- `ReturnArgumentPromise` or `->willReturnArgument($index)` - returns the nth method argument from call
- `ThrowPromise` or `->willThrow($exception)` - causes the method to throw specific exception
- `CallbackPromise` or `->will($callback)` - gives you a quick way to define your own custom logic
Keep in mind, that you can always add even more promises by implementing
`Prophecy\Promise\PromiseInterface`.
#### Method prophecies idempotency
Prophecy enforces same method prophecies and, as a consequence, same promises and
predictions for the same method calls with the same arguments. This means:
```php
$methodProphecy1 = $prophecy->read('123');
$methodProphecy2 = $prophecy->read('123');
$methodProphecy3 = $prophecy->read('321');
$methodProphecy1 === $methodProphecy2;
$methodProphecy1 !== $methodProphecy3;
```
That's interesting, right? Now you might ask me how would you define more complex
behaviors where some method call changes behavior of others. In PHPUnit or Mockery
you do that by predicting how many times your method will be called. In Prophecy,
you'll use promises for that:
```php
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName('everzet')->will(function () {
$this->getName()->willReturn('everzet');
});
// For PHP 5.3
$user->setName('everzet')->will(function ($args, $user) {
$user->getName()->willReturn('everzet');
});
// Or
$user->setName('everzet')->will(function ($args) use ($user) {
$user->getName()->willReturn('everzet');
});
```
And now it doesn't matter how many times or in which order your methods are called.
What matters is their behaviors and how well you faked it.
Note: If the method is called several times, you can use the following syntax to return different
values for each call:
```php
$prophecy->read('123')->willReturn(1, 2, 3);
```
This feature is actually not recommended for most cases. Relying on the order of
calls for the same arguments tends to make test fragile, as adding one more call
can break everything.
#### Arguments wildcarding
The previous example is awesome (at least I hope it is for you), but that's not
optimal enough. We hardcoded `'everzet'` in our expectation. Isn't there a better
way? In fact there is, but it involves understanding what this `'everzet'`
actually is.
You see, even if method arguments used during method prophecy creation look
like simple method arguments, in reality they are not. They are argument token
wildcards. As a matter of fact, `->setName('everzet')` looks like a simple call just
because Prophecy automatically transforms it under the hood into:
```php
$user->setName(new Prophecy\Argument\Token\ExactValueToken('everzet'));
```
Those argument tokens are simple PHP classes, that implement
`Prophecy\Argument\Token\TokenInterface` and tell Prophecy how to compare real arguments
with your expectations. And yes, those classnames are damn big. That's why there's a
shortcut class `Prophecy\Argument`, which you can use to create tokens like that:
```php
use Prophecy\Argument;
$user->setName(Argument::exact('everzet'));
```
`ExactValueToken` is not very useful in our case as it forced us to hardcode the username.
That's why Prophecy comes bundled with a bunch of other tokens:
- `IdenticalValueToken` or `Argument::is($value)` - checks that the argument is identical to a specific value
- `ExactValueToken` or `Argument::exact($value)` - checks that the argument matches a specific value
- `TypeToken` or `Argument::type($typeOrClass)` - checks that the argument matches a specific type or
classname
- `ObjectStateToken` or `Argument::which($method, $value)` - checks that the argument method returns
a specific value
- `CallbackToken` or `Argument::that(callback)` - checks that the argument matches a custom callback
- `AnyValueToken` or `Argument::any()` - matches any argument
- `AnyValuesToken` or `Argument::cetera()` - matches any arguments to the rest of the signature
- `StringContainsToken` or `Argument::containingString($value)` - checks that the argument contains a specific string value
And you can add even more by implementing `TokenInterface` with your own custom classes.
So, let's refactor our initial `{set,get}Name()` logic with argument tokens:
```php
use Prophecy\Argument;
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName(Argument::type('string'))->will(function ($args) {
$this->getName()->willReturn($args[0]);
});
// For PHP 5.3
$user->setName(Argument::type('string'))->will(function ($args, $user) {
$user->getName()->willReturn($args[0]);
});
// Or
$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
$user->getName()->willReturn($args[0]);
});
```
That's it. Now our `{set,get}Name()` prophecy will work with any string argument provided to it.
We've just described how our stub object should behave, even though the original object could have
no behavior whatsoever.
One last bit about arguments now. You might ask, what happens in case of:
```php
use Prophecy\Argument;
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName(Argument::type('string'))->will(function ($args) {
$this->getName()->willReturn($args[0]);
});
// For PHP 5.3
$user->setName(Argument::type('string'))->will(function ($args, $user) {
$user->getName()->willReturn($args[0]);
});
// Or
$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
$user->getName()->willReturn($args[0]);
});
$user->setName(Argument::any())->will(function () {
});
```
Nothing. Your stub will continue behaving the way it did before. That's because of how
arguments wildcarding works. Every argument token type has a different score level, which
wildcard then uses to calculate the final arguments match score and use the method prophecy
promise that has the highest score. In this case, `Argument::type()` in case of success
scores `5` and `Argument::any()` scores `3`. So the type token wins, as does the first
`setName()` method prophecy and its promise. The simple rule of thumb - more precise token
always wins.
#### Getting stub objects
Ok, now we know how to define our prophecy method promises, let's get our stub from
it:
```php
$stub = $prophecy->reveal();
```
As you might see, the only difference between how we get dummies and stubs is that with
stubs we describe every object conversation instead of just agreeing with `null` returns
(object being *dummy*). As a matter of fact, after you define your first promise
(method call), Prophecy will force you to define all the communications - it throws
the `UnexpectedCallException` for any call you didn't describe with object prophecy before
calling it on a stub.
### Mocks
Now we know how to define doubles without behavior (dummies) and doubles with behavior, but
no expectations (stubs). What's left is doubles for which we have some expectations. These
are called mocks and in Prophecy they look almost exactly the same as stubs, except that
they define *predictions* instead of *promises* on method prophecies:
```php
$entityManager->flush()->shouldBeCalled();
```
#### Predictions
The `shouldBeCalled()` method here assigns `CallPrediction` to our method prophecy.
Predictions are a delayed behavior check for your prophecies. You see, during the entire lifetime
of your doubles, Prophecy records every single call you're making against it inside your
code. After that, Prophecy can use this collected information to check if it matches defined
predictions. You can assign predictions to method prophecies using the
`MethodProphecy::should(PredictionInterface $prediction)` method. As a matter of fact,
the `shouldBeCalled()` method we used earlier is just a shortcut to:
```php
$entityManager->flush()->should(new Prophecy\Prediction\CallPrediction());
```
It checks if your method of interest (that matches both the method name and the arguments wildcard)
was called 1 or more times. If the prediction failed then it throws an exception. When does this
check happen? Whenever you call `checkPredictions()` on the main Prophet object:
```php
$prophet->checkPredictions();
```
In PHPUnit, you would want to put this call into the `tearDown()` method. If no predictions
are defined, it would do nothing. So it won't harm to call it after every test.
There are plenty more predictions you can play with:
- `CallPrediction` or `shouldBeCalled()` - checks that the method has been called 1 or more times
- `NoCallsPrediction` or `shouldNotBeCalled()` - checks that the method has not been called
- `CallTimesPrediction` or `shouldBeCalledTimes($count)` - checks that the method has been called
`$count` times
- `CallbackPrediction` or `should($callback)` - checks the method against your own custom callback
Of course, you can always create your own custom prediction any time by implementing
`PredictionInterface`.
### Spies
The last bit of awesomeness in Prophecy is out-of-the-box spies support. As I said in the previous
section, Prophecy records every call made during the double's entire lifetime. This means
you don't need to record predictions in order to check them. You can also do it
manually by using the `MethodProphecy::shouldHave(PredictionInterface $prediction)` method:
```php
$em = $prophet->prophesize('Doctrine\ORM\EntityManager');
$controller->createUser($em->reveal());
$em->flush()->shouldHaveBeenCalled();
```
Such manipulation with doubles is called spying. And with Prophecy it just works.
PK ! ņÅ6} } LICENSEnu ÕIw¶“ Copyright (c) 2013 Konstantin Kudryashov
Marcello Duarte
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
PK ! ĢĀtI% I%
CHANGES.mdnu ÕIw¶“ 1.10.3 / 2020/03/05
===================
* [fixed] removed fatal error when phpdocumentor/reflection-docblock 5 parses an invalid `@method` tag (@stof)
1.10.2 / 2020/01/20
===================
* [added] support for new versions of `sebastian/comparator` and `sebastian/recursion-context` (@sebastianbergmann)
1.10.1 / 2019/12/22
===================
* [fixed] identical callables no longer match as arguments (@ciaranmcnulty)
1.10.0 / 2019/12/17
===================
* [added] shouldHaveBeenCalled evaluation happens later so un-stubbed calls don't throw (@elvetemedve)
* [added] methods can now be doubled case-insensitively to match PHP semantics (@michalbundyra)
* [fixed] reduced memory usage by optimising CachedDoubler (@DonCallisto)
* [fixed] removed fatal error nesting level when comparing large objects (@scroach)
1.9.0 / 2019/10/03
==================
* [added] Add willYield feature to Method Prophecy(@tkotosz)
* [fixed] Allow `MethodProphecy::willThrow()` to accept Throwable as string (@timoschinkel )
* [fixed] Allow new version of phpdocumentor/reflection-docblock (@ricpelo)
1.8.1 / 2019/06/13
==================
* [fixed] Don't try to patch final constructors (@NiR)
1.8.0 / 2018/08/05
==================
* Support for void return types without explicit will (@crellbar)
* Clearer error message for unexpected method calls (@meridius)
* Clearer error message for aggregate exceptions (@meridius)
* More verbose `shouldBeCalledOnce` expectation (@olvlvl)
* Ability to double Throwable, or methods that extend it (@ciaranmcnulty)
* [fixed] Doubling methods where class has additional arguments to interface (@webimpress)
* [fixed] Doubling methods where arguments are nullable but default is not null (@webimpress)
* [fixed] Doubling magic methods on parent class (@dsnopek)
* [fixed] Check method predictions only once (@dontub)
* [fixed] Argument::containingString throwing error when called with non-string (@dcabrejas)
1.7.6 / 2018/04/18
==================
* Allow sebastian/comparator ^3.0 (@sebastianbergmann)
1.7.5 / 2018/02/11
==================
* Support for object return type hints (thanks @greg0ire)
1.7.4 / 2018/02/11
==================
* Fix issues with PHP 7.2 (thanks @greg0ire)
* Support object type hints in PHP 7.2 (thanks @@jansvoboda11)
1.7.3 / 2017/11/24
==================
* Fix SplInfo ClassPatch to work with Symfony 4 (Thanks @gnugat)
1.7.2 / 2017-10-04
==================
* Reverted "check method predictions only once" due to it breaking Spies
1.7.1 / 2017-10-03
==================
* Allow PHP5 keywords methods generation on PHP7 (thanks @bycosta)
* Allow reflection-docblock v4 (thanks @GrahamCampbell)
* Check method predictions only once (thanks @dontub)
* Escape file path sent to \SplFileObjectConstructor when running on Windows (thanks @danmartin-epiphany)
1.7.0 / 2017-03-02
==================
* Add full PHP 7.1 Support (thanks @prolic)
* Allow `sebastian/comparator ^2.0` (thanks @sebastianbergmann)
* Allow `sebastian/recursion-context ^3.0` (thanks @sebastianbergmann)
* Allow `\Error` instances in `ThrowPromise` (thanks @jameshalsall)
* Support `phpspec/phpspect ^3.2` (thanks @Sam-Burns)
* Fix failing builds (thanks @Sam-Burns)
1.6.2 / 2016-11-21
==================
* Added support for detecting @method on interfaces that the class itself implements, or when the stubbed class is an interface itself (thanks @Seldaek)
* Added support for sebastian/recursion-context 2 (thanks @sebastianbergmann)
* Added testing on PHP 7.1 on Travis (thanks @danizord)
* Fixed the usage of the phpunit comparator (thanks @Anyqax)
1.6.1 / 2016-06-07
==================
* Ignored empty method names in invalid `@method` phpdoc
* Fixed the mocking of SplFileObject
* Added compatibility with phpdocumentor/reflection-docblock 3
1.6.0 / 2016-02-15
==================
* Add Variadics support (thanks @pamil)
* Add ProphecyComparator for comparing objects that need revealing (thanks @jon-acker)
* Add ApproximateValueToken (thanks @dantleech)
* Add support for 'self' and 'parent' return type (thanks @bendavies)
* Add __invoke to allowed reflectable methods list (thanks @ftrrtf)
* Updated ExportUtil to reflect the latest changes by Sebastian (thanks @jakari)
* Specify the required php version for composer (thanks @jakzal)
* Exclude 'args' in the generated backtrace (thanks @oradwell)
* Fix code generation for scalar parameters (thanks @trowski)
* Fix missing sprintf in InvalidArgumentException __construct call (thanks @emmanuelballery)
* Fix phpdoc for magic methods (thanks @Tobion)
* Fix PhpDoc for interfaces usage (thanks @ImmRanneft)
* Prevent final methods from being manually extended (thanks @kamioftea)
* Enhance exception for invalid argument to ThrowPromise (thanks @Tobion)
1.5.0 / 2015-04-27
==================
* Add support for PHP7 scalar type hints (thanks @trowski)
* Add support for PHP7 return types (thanks @trowski)
* Update internal test suite to support PHP7
1.4.1 / 2015-04-27
==================
* Fixed bug in closure-based argument tokens (#181)
1.4.0 / 2015-03-27
==================
* Fixed errors in return type phpdocs (thanks @sobit)
* Fixed stringifying of hash containing one value (thanks @avant1)
* Improved clarity of method call expectation exception (thanks @dantleech)
* Add ability to specify which argument is returned in willReturnArgument (thanks @coderbyheart)
* Add more information to MethodNotFound exceptions (thanks @ciaranmcnulty)
* Support for mocking classes with methods that return references (thanks @edsonmedina)
* Improved object comparison (thanks @whatthejeff)
* Adopted '^' in composer dependencies (thanks @GrahamCampbell)
* Fixed non-typehinted arguments being treated as optional (thanks @whatthejeff)
* Magic methods are now filtered for keywords (thanks @seagoj)
* More readable errors for failure when expecting single calls (thanks @dantleech)
1.3.1 / 2014-11-17
==================
* Fix the edge case when failed predictions weren't recorded for `getCheckedPredictions()`
1.3.0 / 2014-11-14
==================
* Add a way to get checked predictions with `MethodProphecy::getCheckedPredictions()`
* Fix HHVM compatibility
* Remove dead code (thanks @stof)
* Add support for DirectoryIterators (thanks @shanethehat)
1.2.0 / 2014-07-18
==================
* Added support for doubling magic methods documented in the class phpdoc (thanks @armetiz)
* Fixed a segfault appearing in some cases (thanks @dmoreaulf)
* Fixed the doubling of methods with typehints on non-existent classes (thanks @gquemener)
* Added support for internal classes using keywords as method names (thanks @milan)
* Added IdenticalValueToken and Argument::is (thanks @florianv)
* Removed the usage of scalar typehints in HHVM as HHVM 3 does not support them anymore in PHP code (thanks @whatthejeff)
1.1.2 / 2014-01-24
==================
* Spy automatically promotes spied method call to an expected one
1.1.1 / 2014-01-15
==================
* Added support for HHVM
1.1.0 / 2014-01-01
==================
* Changed the generated class names to use a static counter instead of a random number
* Added a clss patch for ReflectionClass::newInstance to make its argument optional consistently (thanks @docteurklein)
* Fixed mirroring of classes with typehints on non-existent classes (thanks @docteurklein)
* Fixed the support of array callables in CallbackPromise and CallbackPrediction (thanks @ciaranmcnulty)
* Added support for properties in ObjectStateToken (thanks @adrienbrault)
* Added support for mocking classes with a final constructor (thanks @ciaranmcnulty)
* Added ArrayEveryEntryToken and Argument::withEveryEntry() (thanks @adrienbrault)
* Added an exception when trying to prophesize on a final method instead of ignoring silently (thanks @docteurklein)
* Added StringContainToken and Argument::containingString() (thanks @peterjmit)
* Added ``shouldNotHaveBeenCalled`` on the MethodProphecy (thanks @ciaranmcnulty)
* Fixed the comparison of objects in ExactValuetoken (thanks @sstok)
* Deprecated ``shouldNotBeenCalled`` in favor of ``shouldNotHaveBeenCalled``
1.0.4 / 2013-08-10
==================
* Better randomness for generated class names (thanks @sstok)
* Add support for interfaces into TypeToken and Argument::type() (thanks @sstok)
* Add support for old-style (method name === class name) constructors (thanks @l310 for report)
1.0.3 / 2013-07-04
==================
* Support callable typehints (thanks @stof)
* Do not attempt to autoload arrays when generating code (thanks @MarcoDeBortoli)
* New ArrayEntryToken (thanks @kagux)
1.0.2 / 2013-05-19
==================
* Logical `AND` token added (thanks @kagux)
* Logical `NOT` token added (thanks @kagux)
* Add support for setting custom constructor arguments
* Properly stringify hashes
* Record calls that throw exceptions
* Migrate spec suite to PhpSpec 2.0
1.0.1 / 2013-04-30
==================
* Fix broken UnexpectedCallException message
* Trim AggregateException message
1.0.0 / 2013-04-29
==================
* Improve exception messages
1.0.0-BETA2 / 2013-04-03
========================
* Add more debug information to CallTimes and Call prediction exception messages
* Fix MethodNotFoundException wrong namespace (thanks @gunnarlium)
* Fix some typos in the exception messages (thanks @pborreli)
1.0.0-BETA1 / 2013-03-25
========================
* Initial release
PK ! Ļ Øq q
composer.jsonnu ÕIw¶“ {
"name": "phpspec/prophecy",
"description": "Highly opinionated mocking framework for PHP 5.3+",
"keywords": ["Mock", "Stub", "Dummy", "Double", "Fake", "Spy"],
"homepage": "https://github.com/phpspec/prophecy",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"require": {
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
"sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
"doctrine/instantiator": "^1.0.2",
"sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
},
"require-dev": {
"phpspec/phpspec": "^2.5 || ^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
},
"autoload": {
"psr-4": {
"Prophecy\\": "src/Prophecy"
}
},
"autoload-dev": {
"psr-4": {
"Fixtures\\Prophecy\\": "fixtures"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.10.x-dev"
}
}
}
PK !
ĪŁ¹ ¹ src/Prophecy/Call/CallCenter.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\Call;
use Prophecy\Exception\Prophecy\MethodProphecyException;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Argument\ArgumentsWildcard;
use Prophecy\Util\StringUtil;
use Prophecy\Exception\Call\UnexpectedCallException;
use SplObjectStorage;
/**
* Calls receiver & manager.
*
* @author Konstantin Kudryashov
*/
class CallCenter
{
private $util;
/**
* @var Call[]
*/
private $recordedCalls = array();
/**
* @var SplObjectStorage
*/
private $unexpectedCalls;
/**
* Initializes call center.
*
* @param StringUtil $util
*/
public function __construct(StringUtil $util = null)
{
$this->util = $util ?: new StringUtil;
$this->unexpectedCalls = new SplObjectStorage();
}
/**
* Makes and records specific method call for object prophecy.
*
* @param ObjectProphecy $prophecy
* @param string $methodName
* @param array $arguments
*
* @return mixed Returns null if no promise for prophecy found or promise return value.
*
* @throws \Prophecy\Exception\Call\UnexpectedCallException If no appropriate method prophecy found
*/
public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments)
{
// For efficiency exclude 'args' from the generated backtrace
if (PHP_VERSION_ID >= 50400) {
// Limit backtrace to last 3 calls as we don't use the rest
// Limit argument was introduced in PHP 5.4.0
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
} elseif (defined('DEBUG_BACKTRACE_IGNORE_ARGS')) {
// DEBUG_BACKTRACE_IGNORE_ARGS was introduced in PHP 5.3.6
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
} else {
$backtrace = debug_backtrace();
}
$file = $line = null;
if (isset($backtrace[2]) && isset($backtrace[2]['file'])) {
$file = $backtrace[2]['file'];
$line = $backtrace[2]['line'];
}
// If no method prophecies defined, then it's a dummy, so we'll just return null
if ('__destruct' === strtolower($methodName) || 0 == count($prophecy->getMethodProphecies())) {
$this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line);
return null;
}
// There are method prophecies, so it's a fake/stub. Searching prophecy for this call
$matches = $this->findMethodProphecies($prophecy, $methodName, $arguments);
// If fake/stub doesn't have method prophecy for this call - throw exception
if (!count($matches)) {
$this->unexpectedCalls->attach(new Call($methodName, $arguments, null, null, $file, $line), $prophecy);
$this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line);
return null;
}
// Sort matches by their score value
@usort($matches, function ($match1, $match2) { return $match2[0] - $match1[0]; });
$score = $matches[0][0];
// If Highest rated method prophecy has a promise - execute it or return null instead
$methodProphecy = $matches[0][1];
$returnValue = null;
$exception = null;
if ($promise = $methodProphecy->getPromise()) {
try {
$returnValue = $promise->execute($arguments, $prophecy, $methodProphecy);
} catch (\Exception $e) {
$exception = $e;
}
}
if ($methodProphecy->hasReturnVoid() && $returnValue !== null) {
throw new MethodProphecyException(
"The method \"$methodName\" has a void return type, but the promise returned a value",
$methodProphecy
);
}
$this->recordedCalls[] = $call = new Call(
$methodName, $arguments, $returnValue, $exception, $file, $line
);
$call->addScore($methodProphecy->getArgumentsWildcard(), $score);
if (null !== $exception) {
throw $exception;
}
return $returnValue;
}
/**
* Searches for calls by method name & arguments wildcard.
*
* @param string $methodName
* @param ArgumentsWildcard $wildcard
*
* @return Call[]
*/
public function findCalls($methodName, ArgumentsWildcard $wildcard)
{
$methodName = strtolower($methodName);
return array_values(
array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) {
return $methodName === strtolower($call->getMethodName())
&& 0 < $call->getScore($wildcard)
;
})
);
}
/**
* @throws UnexpectedCallException
*/
public function checkUnexpectedCalls()
{
/** @var Call $call */
foreach ($this->unexpectedCalls as $call) {
$prophecy = $this->unexpectedCalls[$call];
// If fake/stub doesn't have method prophecy for this call - throw exception
if (!count($this->findMethodProphecies($prophecy, $call->getMethodName(), $call->getArguments()))) {
throw $this->createUnexpectedCallException($prophecy, $call->getMethodName(), $call->getArguments());
}
}
}
private function createUnexpectedCallException(ObjectProphecy $prophecy, $methodName,
array $arguments)
{
$classname = get_class($prophecy->reveal());
$indentationLength = 8; // looks good
$argstring = implode(
",\n",
$this->indentArguments(
array_map(array($this->util, 'stringify'), $arguments),
$indentationLength
)
);
$expected = array();
foreach (call_user_func_array('array_merge', $prophecy->getMethodProphecies()) as $methodProphecy) {
$expected[] = sprintf(
" - %s(\n" .
"%s\n" .
" )",
$methodProphecy->getMethodName(),
implode(
",\n",
$this->indentArguments(
array_map('strval', $methodProphecy->getArgumentsWildcard()->getTokens()),
$indentationLength
)
)
);
}
return new UnexpectedCallException(
sprintf(
"Unexpected method call on %s:\n".
" - %s(\n".
"%s\n".
" )\n".
"expected calls were:\n".
"%s",
$classname, $methodName, $argstring, implode("\n", $expected)
),
$prophecy, $methodName, $arguments
);
}
private function indentArguments(array $arguments, $indentationLength)
{
return preg_replace_callback(
'/^/m',
function () use ($indentationLength) {
return str_repeat(' ', $indentationLength);
},
$arguments
);
}
/**
* @param ObjectProphecy $prophecy
* @param string $methodName
* @param array $arguments
*
* @return array
*/
private function findMethodProphecies(ObjectProphecy $prophecy, $methodName, array $arguments)
{
$matches = array();
foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) {
if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) {
$matches[] = array($score, $methodProphecy);
}
}
return $matches;
}
}
PK ! 8VuŁ
src/Prophecy/Call/Call.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\Call;
use Exception;
use Prophecy\Argument\ArgumentsWildcard;
/**
* Call object.
*
* @author Konstantin Kudryashov
*/
class Call
{
private $methodName;
private $arguments;
private $returnValue;
private $exception;
private $file;
private $line;
private $scores;
/**
* Initializes call.
*
* @param string $methodName
* @param array $arguments
* @param mixed $returnValue
* @param Exception $exception
* @param null|string $file
* @param null|int $line
*/
public function __construct($methodName, array $arguments, $returnValue,
Exception $exception = null, $file, $line)
{
$this->methodName = $methodName;
$this->arguments = $arguments;
$this->returnValue = $returnValue;
$this->exception = $exception;
$this->scores = new \SplObjectStorage();
if ($file) {
$this->file = $file;
$this->line = intval($line);
}
}
/**
* Returns called method name.
*
* @return string
*/
public function getMethodName()
{
return $this->methodName;
}
/**
* Returns called method arguments.
*
* @return array
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Returns called method return value.
*
* @return null|mixed
*/
public function getReturnValue()
{
return $this->returnValue;
}
/**
* Returns exception that call thrown.
*
* @return null|Exception
*/
public function getException()
{
return $this->exception;
}
/**
* Returns callee filename.
*
* @return string
*/
public function getFile()
{
return $this->file;
}
/**
* Returns callee line number.
*
* @return int
*/
public function getLine()
{
return $this->line;
}
/**
* Returns short notation for callee place.
*
* @return string
*/
public function getCallPlace()
{
if (null === $this->file) {
return 'unknown';
}
return sprintf('%s:%d', $this->file, $this->line);
}
/**
* Adds the wildcard match score for the provided wildcard.
*
* @param ArgumentsWildcard $wildcard
* @param false|int $score
*
* @return $this
*/
public function addScore(ArgumentsWildcard $wildcard, $score)
{
$this->scores[$wildcard] = $score;
return $this;
}
/**
* Returns wildcard match score for the provided wildcard. The score is
* calculated if not already done.
*
* @param ArgumentsWildcard $wildcard
*
* @return false|int False OR integer score (higher - better)
*/
public function getScore(ArgumentsWildcard $wildcard)
{
if (isset($this->scores[$wildcard])) {
return $this->scores[$wildcard];
}
return $this->scores[$wildcard] = $wildcard->scoreArguments($this->getArguments());
}
}
PK ! Öi§Ō Ō # src/Prophecy/Comparator/Factory.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\Comparator;
use SebastianBergmann\Comparator\Factory as BaseFactory;
/**
* Prophecy comparator factory.
*
* @author Konstantin Kudryashov
*/
final class Factory extends BaseFactory
{
/**
* @var Factory
*/
private static $instance;
public function __construct()
{
parent::__construct();
$this->register(new ClosureComparator());
$this->register(new ProphecyComparator());
}
/**
* @return Factory
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new Factory;
}
return self::$instance;
}
}
PK ! ¤hĒs s . src/Prophecy/Comparator/ProphecyComparator.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\Comparator;
use Prophecy\Prophecy\ProphecyInterface;
use SebastianBergmann\Comparator\ObjectComparator;
class ProphecyComparator extends ObjectComparator
{
public function accepts($expected, $actual)
{
return is_object($expected) && is_object($actual) && $actual instanceof ProphecyInterface;
}
public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array())
{
parent::assertEquals($expected, $actual->reveal(), $delta, $canonicalize, $ignoreCase, $processed);
}
}
PK ! Ē Ē - src/Prophecy/Comparator/ClosureComparator.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\Comparator;
use SebastianBergmann\Comparator\Comparator;
use SebastianBergmann\Comparator\ComparisonFailure;
/**
* Closure comparator.
*
* @author Konstantin Kudryashov
*/
final class ClosureComparator extends Comparator
{
public function accepts($expected, $actual)
{
return is_object($expected) && $expected instanceof \Closure
&& is_object($actual) && $actual instanceof \Closure;
}
public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array())
{
if ($expected !== $actual) {
throw new ComparisonFailure(
$expected,
$actual,
// we don't need a diff
'',
'',
false,
'all closures are different if not identical'
);
}
}
}
PK ! u9o o 6 src/Prophecy/PhpDocumentor/LegacyClassTagRetriever.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\PhpDocumentor;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
/**
* @author ThƩo FIDRY
*
* @internal
*/
final class LegacyClassTagRetriever implements MethodTagRetrieverInterface
{
/**
* @param \ReflectionClass $reflectionClass
*
* @return LegacyMethodTag[]
*/
public function getTagList(\ReflectionClass $reflectionClass)
{
$phpdoc = new DocBlock($reflectionClass->getDocComment());
return $phpdoc->getTagsByName('method');
}
}
PK ! g¼Z 0 src/Prophecy/PhpDocumentor/ClassTagRetriever.phpnu ÕIw¶“
* Marcello Duarte
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Prophecy\PhpDocumentor;
use phpDocumentor\Reflection\DocBlock\Tags\Method;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\Types\ContextFactory;
/**
* @author ThƩo FIDRY
*
* @internal
*/
final class ClassTagRetriever implements MethodTagRetrieverInterface
{
private $docBlockFactory;
private $contextFactory;
public function __construct()
{
$this->docBlockFactory = DocBlockFactory::createInstance();
$this->contextFactory = new ContextFactory();
}
/**
* @param \ReflectionClass $reflectionClass
*
* @return Method[]
*/
public function getTagList(\ReflectionClass $reflectionClass)
{
try {
$phpdoc = $this->docBlockFactory->create(
$reflectionClass,
$this->contextFactory->createFromReflector($reflectionClass)
);
$methods = array();
foreach ($phpdoc->getTagsByName('method') as $tag) {
if ($tag instanceof Method) {
$methods[] = $tag;
}
}
return $methods;
} catch (\InvalidArgumentException $e) {
return array();
}
}
}
PK ! rЬx x <