Upgrade framework
This commit is contained in:
12
vendor/mockery/mockery/.gitignore
vendored
12
vendor/mockery/mockery/.gitignore
vendored
@@ -1,12 +0,0 @@
|
||||
*~
|
||||
pearfarm.spec
|
||||
*.sublime-project
|
||||
library/Hamcrest/*
|
||||
composer.lock
|
||||
vendor/
|
||||
composer.phar
|
||||
test.php
|
||||
build/
|
||||
phpunit.xml
|
||||
*.DS_store
|
||||
.idea/*
|
||||
14
vendor/mockery/mockery/.php_cs
vendored
14
vendor/mockery/mockery/.php_cs
vendored
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
$finder = Symfony\CS\Finder\DefaultFinder::create()
|
||||
->exclude('examples')
|
||||
->exclude('docs')
|
||||
->exclude('travis')
|
||||
->exclude('vendor')
|
||||
->exclude('tests/Mockery/_files')
|
||||
->exclude('tests/Mockery/_files')
|
||||
->in(__DIR__);
|
||||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->level('psr2')
|
||||
->finder($finder);
|
||||
11
vendor/mockery/mockery/.phpstorm.meta.php
vendored
Normal file
11
vendor/mockery/mockery/.phpstorm.meta.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace PHPSTORM_META;
|
||||
|
||||
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(["" => "@"]));
|
||||
24
vendor/mockery/mockery/.scrutinizer.yml
vendored
24
vendor/mockery/mockery/.scrutinizer.yml
vendored
@@ -1,24 +0,0 @@
|
||||
filter:
|
||||
paths: [library/*]
|
||||
excluded_paths: [vendor/*, tests/*, examples/*]
|
||||
before_commands:
|
||||
- 'composer install --dev --prefer-source'
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 300
|
||||
php_code_sniffer: true
|
||||
php_cpd:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
php_pdepend:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
php_loc:
|
||||
enabled: true
|
||||
excluded_dirs: [vendor, tests, examples]
|
||||
php_hhvm: false
|
||||
php_mess_detector: true
|
||||
php_analyzer: true
|
||||
changetracking:
|
||||
bug_patterns: ["\bfix(?:es|ed)?\b"]
|
||||
feature_patterns: ["\badd(?:s|ed)?\b", "\bimplement(?:s|ed)?\b"]
|
||||
1
vendor/mockery/mockery/.styleci.yml
vendored
1
vendor/mockery/mockery/.styleci.yml
vendored
@@ -1 +0,0 @@
|
||||
preset: psr2
|
||||
42
vendor/mockery/mockery/.travis.yml
vendored
42
vendor/mockery/mockery/.travis.yml
vendored
@@ -1,42 +0,0 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
- hhvm-nightly
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: hhvm-nightly
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
|
||||
install:
|
||||
- travis_retry ./travis/install.sh
|
||||
|
||||
before_script:
|
||||
- ./travis/before_script.sh
|
||||
|
||||
script:
|
||||
- ./travis/script.sh
|
||||
|
||||
after_success:
|
||||
- ./travis/after_success.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- padraic.brady@gmail.com
|
||||
- dave@atstsolutions.co.uk
|
||||
irc: "irc.freenode.org#mockery"
|
||||
175
vendor/mockery/mockery/CHANGELOG.md
vendored
175
vendor/mockery/mockery/CHANGELOG.md
vendored
@@ -1,5 +1,178 @@
|
||||
# Change Log
|
||||
|
||||
## 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)
|
||||
* 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)
|
||||
|
||||
## 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)
|
||||
|
||||
* 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)
|
||||
|
||||
## 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)
|
||||
|
||||
## 1.2.2 (2019-02-13)
|
||||
|
||||
* 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)
|
||||
|
||||
## 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)
|
||||
|
||||
## 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)
|
||||
|
||||
## 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
|
||||
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
|
||||
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`
|
||||
@@ -19,7 +192,7 @@
|
||||
|
||||
## 0.9.2 (2014-09-03)
|
||||
|
||||
* Some workarounds for the serilisation 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
|
||||
foo->baz, we'll attempt to use the same foo
|
||||
|
||||
5
vendor/mockery/mockery/CONTRIBUTING.md
vendored
5
vendor/mockery/mockery/CONTRIBUTING.md
vendored
@@ -39,7 +39,6 @@ but we'll probably merge any code that looks close enough.
|
||||
* 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
|
||||
* If you have created new library files, add them to the root package.xml file for PEAR install support.
|
||||
* Send a [Pull
|
||||
Request](https://help.github.com/articles/creating-a-pull-request) to the
|
||||
correct target branch (see below)
|
||||
@@ -66,7 +65,7 @@ e.g. 0.8.
|
||||
|
||||
To run the unit tests for Mockery, clone the git repository, download Composer using
|
||||
the instructions at [http://getcomposer.org/download/](http://getcomposer.org/download/),
|
||||
then install the dependencies with `php /path/to/composer.phar install --dev`.
|
||||
then install the dependencies with `php /path/to/composer.phar install`.
|
||||
|
||||
This will install the required PHPUnit and Hamcrest dev dependencies and create the
|
||||
autoload files required by the unit tests. You may run the `vendor/bin/phpunit` command
|
||||
@@ -75,7 +74,7 @@ to run the unit tests. If everything goes to plan, there will be no failed tests
|
||||
|
||||
## Debugging Mockery
|
||||
|
||||
Mockery and it's code generation can be difficult to debug. A good start is to
|
||||
Mockery and its code generation can be difficult to debug. A good start is to
|
||||
use the `RequireLoader`, which will dump the code generated by mockery to a file
|
||||
before requiring it, rather than using eval. This will help with stack traces,
|
||||
and you will be able to open the mock class in your editor.
|
||||
|
||||
2
vendor/mockery/mockery/LICENSE
vendored
2
vendor/mockery/mockery/LICENSE
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2010-2014, Pádraic Brady
|
||||
Copyright (c) 2010, Pádraic Brady
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
283
vendor/mockery/mockery/README.md
vendored
283
vendor/mockery/mockery/README.md
vendored
@@ -1,10 +1,9 @@
|
||||
Mockery
|
||||
=======
|
||||
|
||||
[](http://travis-ci.org/padraic/mockery)
|
||||
[](https://packagist.org/packages/mockery/mockery)
|
||||
[](https://packagist.org/packages/mockery/mockery)
|
||||
|
||||
[](https://github.com/mockery/mockery/actions)
|
||||
[](https://packagist.org/packages/mockery/mockery)
|
||||
[](https://packagist.org/packages/mockery/mockery)
|
||||
|
||||
Mockery is a simple yet flexible PHP mock object framework for use in unit testing
|
||||
with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a
|
||||
@@ -16,53 +15,277 @@ phpunit-mock-objects without the World ending.
|
||||
|
||||
Mockery is released under a New BSD License.
|
||||
|
||||
The current released version on Packagist is 0.9.3.
|
||||
The current released version for PEAR is 0.9.0. Composer users may instead opt to use
|
||||
the current master branch aliased to 0.9.x-dev.
|
||||
|
||||
## Installation
|
||||
|
||||
To install Mockery, run the command below and you will get the latest
|
||||
version
|
||||
|
||||
```sh
|
||||
composer require mockery/mockery
|
||||
composer require --dev mockery/mockery
|
||||
```
|
||||
|
||||
If you want to run the tests:
|
||||
## Documentation
|
||||
|
||||
```sh
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
In older versions, this README file was the documentation for Mockery. Over time
|
||||
we have improved this, and have created an extensive documentation for you. Please
|
||||
use this README file as a starting point for Mockery, but do read the documentation
|
||||
to learn how to use Mockery.
|
||||
|
||||
####Note
|
||||
The current version can be seen at [docs.mockery.io](http://docs.mockery.io).
|
||||
|
||||
The future Mockery 0.9.4 release will be the final version to have PHP 5.3
|
||||
as a minimum requirement. The minimum PHP requirement will thereafter move to
|
||||
PHP 5.4. Also, the PEAR channel will go offline permanently no earlier than 30
|
||||
June 2015.
|
||||
## PHPUnit Integration
|
||||
|
||||
## Mock Objects
|
||||
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.
|
||||
|
||||
In unit tests, mock objects simulate the behaviour of real objects. They are
|
||||
## Test Doubles
|
||||
|
||||
Test doubles (often called mocks) simulate the behaviour of real objects. They are
|
||||
commonly utilised to offer test isolation, to stand in for objects which do not
|
||||
yet exist, or to allow for the exploratory design of class APIs without
|
||||
requiring actual implementation up front.
|
||||
|
||||
The benefits of a mock object framework are to allow for the flexible generation
|
||||
of such mock objects (and stubs). They allow the setting of expected method calls
|
||||
and return values using a flexible API which is capable of capturing every
|
||||
The benefits of a test double framework are to allow for the flexible generation
|
||||
and configuration of test doubles. They allow the setting of expected method calls
|
||||
and/or return values using a flexible API which is capable of capturing every
|
||||
possible real object behaviour in way that is stated as close as possible to a
|
||||
natural language description.
|
||||
natural language description. Use the `Mockery::mock` method to create a test
|
||||
double.
|
||||
|
||||
``` php
|
||||
$double = Mockery::mock();
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
If you need Mockery to create a test double to satisfy a particular type hint,
|
||||
you can pass the type to the `mock` method.
|
||||
|
||||
Mockery requires PHP 5.3.2 or greater. In addition, it is recommended to install
|
||||
the Hamcrest library (see below for instructions) which contains additional
|
||||
matchers used when defining expected method arguments.
|
||||
``` php
|
||||
class Book {}
|
||||
|
||||
interface BookRepository {
|
||||
function find($id): Book;
|
||||
function findAll(): array;
|
||||
function add(Book $book): void;
|
||||
}
|
||||
|
||||
## Documentation
|
||||
$double = Mockery::mock(BookRepository::class);
|
||||
```
|
||||
|
||||
The current version can be seen at [docs.mockery.io](http://docs.mockery.io).
|
||||
A detailed explanation of creating and working with test doubles is given in the
|
||||
documentation, [Creating test doubles](http://docs.mockery.io/en/latest/reference/creating_test_doubles.html)
|
||||
section.
|
||||
|
||||
## Method Stubs 🎫
|
||||
|
||||
A method stub is a mechanism for having your test double return canned responses
|
||||
to certain method calls. With stubs, you don't care how many times, if at all,
|
||||
the method is called. Stubs are used to provide indirect input to the system
|
||||
under test.
|
||||
|
||||
``` php
|
||||
$double->allows()->find(123)->andReturns(new Book());
|
||||
|
||||
$book = $double->find(123);
|
||||
```
|
||||
|
||||
If you have used Mockery before, you might see something new in the example
|
||||
above — we created a method stub using `allows`, instead of the "old"
|
||||
`shouldReceive` syntax. This is a new feature of Mockery v1, but fear not,
|
||||
the trusty ol' `shouldReceive` is still here.
|
||||
|
||||
For new users of Mockery, the above example can also be written as:
|
||||
|
||||
``` php
|
||||
$double->shouldReceive('find')->with(123)->andReturn(new Book());
|
||||
$book = $double->find(123);
|
||||
```
|
||||
|
||||
If your stub doesn't require specific arguments, you can also use this shortcut
|
||||
for setting up multiple calls at once:
|
||||
|
||||
``` php
|
||||
$double->allows([
|
||||
"findAll" => [new Book(), new Book()],
|
||||
]);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
``` php
|
||||
$double->shouldReceive('findAll')
|
||||
->andReturn([new Book(), new Book()]);
|
||||
```
|
||||
|
||||
You can also use this shortcut, which creates a double and sets up some stubs in
|
||||
one call:
|
||||
|
||||
``` php
|
||||
$double = Mockery::mock(BookRepository::class, [
|
||||
"findAll" => [new Book(), new Book()],
|
||||
]);
|
||||
```
|
||||
|
||||
## Method Call Expectations 📲
|
||||
|
||||
A Method call expectation is a mechanism to allow you to verify that a
|
||||
particular method has been called. You can specify the parameters and you can
|
||||
also specify how many times you expect it to be called. Method call expectations
|
||||
are used to verify indirect output of the system under test.
|
||||
|
||||
``` php
|
||||
$book = new Book();
|
||||
|
||||
$double = Mockery::mock(BookRepository::class);
|
||||
$double->expects()->add($book);
|
||||
```
|
||||
|
||||
During the test, Mockery accept calls to the `add` method as prescribed.
|
||||
After you have finished exercising the system under test, you need to
|
||||
tell Mockery to check that the method was called as expected, using the
|
||||
`Mockery::close` method. One way to do that is to add it to your `tearDown`
|
||||
method in PHPUnit.
|
||||
|
||||
``` php
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
Mockery::close();
|
||||
}
|
||||
```
|
||||
|
||||
The `expects()` method automatically sets up an expectation that the method call
|
||||
(and matching parameters) is called **once and once only**. You can choose to change
|
||||
this if you are expecting more calls.
|
||||
|
||||
``` php
|
||||
$double->expects()->add($book)->twice();
|
||||
```
|
||||
|
||||
If you have used Mockery before, you might see something new in the example
|
||||
above — 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.
|
||||
|
||||
For new users of Mockery, the above example can also be written as:
|
||||
|
||||
``` php
|
||||
$double->shouldReceive('find')
|
||||
->with(123)
|
||||
->once()
|
||||
->andReturn(new Book());
|
||||
$book = $double->find(123);
|
||||
```
|
||||
|
||||
A detailed explanation of declaring expectations on method calls, please
|
||||
read the documentation, the [Expectation declarations](http://docs.mockery.io/en/latest/reference/expectations.html)
|
||||
section. After that, you can also learn about the new `allows` and `expects` methods
|
||||
in the [Alternative shouldReceive syntax](http://docs.mockery.io/en/latest/reference/alternative_should_receive_syntax.html)
|
||||
section.
|
||||
|
||||
It is worth mentioning that one way of setting up expectations is no better or worse
|
||||
than the other. Under the hood, `allows` and `expects` are doing the same thing as
|
||||
`shouldReceive`, at times in "less words", and as such it comes to a personal preference
|
||||
of the programmer which way to use.
|
||||
|
||||
## Test Spies 🕵️
|
||||
|
||||
By default, all test doubles created with the `Mockery::mock` method will only
|
||||
accept calls that they have been configured to `allow` or `expect` (or in other words,
|
||||
calls that they `shouldReceive`). Sometimes we don't necessarily care about all of the
|
||||
calls that are going to be made to an object. To facilitate this, we can tell Mockery
|
||||
to ignore any calls it has not been told to expect or allow. To do so, we can tell a
|
||||
test double `shouldIgnoreMissing`, or we can create the double using the `Mocker::spy`
|
||||
shortcut.
|
||||
|
||||
``` php
|
||||
// $double = Mockery::mock()->shouldIgnoreMissing();
|
||||
$double = Mockery::spy();
|
||||
|
||||
$double->foo(); // null
|
||||
$double->bar(); // null
|
||||
```
|
||||
|
||||
Further to this, sometimes we want to have the object accept any call during the test execution
|
||||
and then verify the calls afterwards. For these purposes, we need our test
|
||||
double to act as a Spy. All mockery test doubles record the calls that are made
|
||||
to them for verification afterwards by default:
|
||||
|
||||
``` php
|
||||
$double->baz(123);
|
||||
|
||||
$double->shouldHaveReceived()->baz(123); // null
|
||||
$double->shouldHaveReceived()->baz(12345); // Uncaught Exception Mockery\Exception\InvalidCountException...
|
||||
```
|
||||
|
||||
Please refer to the [Spies](http://docs.mockery.io/en/latest/reference/spies.html) section
|
||||
of the documentation to learn more about the spies.
|
||||
|
||||
## Utilities 🔌
|
||||
|
||||
### Global Helpers
|
||||
|
||||
Mockery ships with a handful of global helper methods, you just need to ask
|
||||
Mockery to declare them.
|
||||
|
||||
``` php
|
||||
Mockery::globalHelpers();
|
||||
|
||||
$mock = mock(Some::class);
|
||||
$spy = spy(Some::class);
|
||||
|
||||
$spy->shouldHaveReceived()
|
||||
->foo(anyArgs());
|
||||
```
|
||||
|
||||
All of the global helpers are wrapped in a `!function_exists` call to avoid
|
||||
conflicts. So if you already have a global function called `spy`, Mockery will
|
||||
silently skip the declaring its own `spy` function.
|
||||
|
||||
### Testing Traits
|
||||
|
||||
As Mockery ships with code generation capabilities, it was trivial to add
|
||||
functionality allowing users to create objects on the fly that use particular
|
||||
traits. Any abstract methods defined by the trait will be created and can have
|
||||
expectations or stubs configured like normal Test Doubles.
|
||||
|
||||
``` php
|
||||
trait Foo {
|
||||
function foo() {
|
||||
return $this->doFoo();
|
||||
}
|
||||
|
||||
abstract function doFoo();
|
||||
}
|
||||
|
||||
$double = Mockery::mock(Foo::class);
|
||||
$double->allows()->doFoo()->andReturns(123);
|
||||
$double->foo(); // int(123)
|
||||
```
|
||||
|
||||
## Versioning
|
||||
|
||||
The Mockery team attempts to adhere to [Semantic Versioning](http://semver.org),
|
||||
however, some of Mockery's internals are considered private and will be open to
|
||||
change at any time. Just because a class isn't final, or a method isn't marked
|
||||
private, does not mean it constitutes part of the API we guarantee under the
|
||||
versioning scheme.
|
||||
|
||||
### Alternative Runtimes
|
||||
|
||||
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
|
||||
|
||||
⚠️️ Update your remotes! Mockery has transferred to a new location. While it was once
|
||||
at `padraic/mockery`, it is now at `mockery/mockery`. While your
|
||||
existing repositories will redirect transparently for any operations, take some
|
||||
time to transition to the new URL.
|
||||
```sh
|
||||
$ git remote set-url upstream https://github.com/mockery/mockery.git
|
||||
```
|
||||
Replace `upstream` with the name of the remote you use locally; `upstream` is commonly
|
||||
used but you may be using something else. Run `git remote -v` to see what you're actually
|
||||
using.
|
||||
|
||||
43
vendor/mockery/mockery/composer.json
vendored
43
vendor/mockery/mockery/composer.json
vendored
@@ -1,8 +1,22 @@
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
"description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
|
||||
"keywords": ["library", "testing", "test", "stub", "mock", "mockery", "test double", "tdd", "bdd", "mock objects"],
|
||||
"homepage": "http://github.com/padraic/mockery",
|
||||
"description": "Mockery is a simple yet flexible PHP mock object framework",
|
||||
"scripts": {
|
||||
"docs": "phpdoc -d library -t docs/api"
|
||||
},
|
||||
"keywords": [
|
||||
"bdd",
|
||||
"library",
|
||||
"mock",
|
||||
"mock objects",
|
||||
"mockery",
|
||||
"stub",
|
||||
"tdd",
|
||||
"test",
|
||||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"homepage": "https://github.com/mockery/mockery",
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
@@ -17,19 +31,32 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"lib-pcre": ">=7.0",
|
||||
"hamcrest/hamcrest-php": "~1.1"
|
||||
"hamcrest/hamcrest-php": "^2.0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
"phpunit/phpunit": "^8.5 || ^9.3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Mockery": "library/" }
|
||||
"psr-0": {
|
||||
"Mockery": "library/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.9.x-dev"
|
||||
"dev-master": "1.4.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
vendor/mockery/mockery/docs/.gitignore
vendored
1
vendor/mockery/mockery/docs/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
_build
|
||||
177
vendor/mockery/mockery/docs/Makefile
vendored
177
vendor/mockery/mockery/docs/Makefile
vendored
@@ -1,177 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MockeryDocs.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MockeryDocs.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/MockeryDocs"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MockeryDocs"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
20
vendor/mockery/mockery/docs/conf.py
vendored
20
vendor/mockery/mockery/docs/conf.py
vendored
@@ -46,16 +46,16 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Mockery Docs'
|
||||
copyright = u'2014, Pádraic Brady, Dave Marshall, Wouter, Graham Campbell'
|
||||
copyright = u'Pádraic Brady, Dave Marshall and contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.9'
|
||||
version = '1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.9'
|
||||
release = '1.0-alpha'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -187,7 +187,7 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index2', 'MockeryDocs.tex', u'Mockery Docs Documentation',
|
||||
('index', 'MockeryDocs.tex', u'Mockery Docs Documentation',
|
||||
u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell', 'manual'),
|
||||
]
|
||||
|
||||
@@ -217,7 +217,7 @@ latex_documents = [
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index2', 'mockerydocs', u'Mockery Docs Documentation',
|
||||
('index', 'mockerydocs', u'Mockery Docs Documentation',
|
||||
[u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell'], 1)
|
||||
]
|
||||
|
||||
@@ -231,7 +231,7 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index2', 'MockeryDocs', u'Mockery Docs Documentation',
|
||||
('index', 'MockeryDocs', u'Mockery Docs Documentation',
|
||||
u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell', 'MockeryDocs', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
@@ -257,3 +257,11 @@ if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
print sphinx_rtd_theme.get_html_theme_path()
|
||||
|
||||
# load PhpLexer
|
||||
from sphinx.highlighting import lexers
|
||||
from pygments.lexers.web import PhpLexer
|
||||
|
||||
# enable highlighting for PHP code not between <?php ... ?> by default
|
||||
lexers['php'] = PhpLexer(startinline=True)
|
||||
lexers['php-annotations'] = PhpLexer(startinline=True)
|
||||
|
||||
52
vendor/mockery/mockery/docs/cookbook/big_parent_class.rst
vendored
Normal file
52
vendor/mockery/mockery/docs/cookbook/big_parent_class.rst
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
.. index::
|
||||
single: Cookbook; Big Parent Class
|
||||
|
||||
Big Parent Class
|
||||
================
|
||||
|
||||
In some application code, especially older legacy code, we can come across some
|
||||
classes that extend a "big parent class" - a parent class that knows and does
|
||||
too much:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class BigParentClass
|
||||
{
|
||||
public function doesEverything()
|
||||
{
|
||||
// sets up database connections
|
||||
// writes to log files
|
||||
}
|
||||
}
|
||||
|
||||
class ChildClass extends BigParentClass
|
||||
{
|
||||
public function doesOneThing()
|
||||
{
|
||||
// but calls on BigParentClass methods
|
||||
$result = $this->doesEverything();
|
||||
// does something with $result
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
We want to test our ``ChildClass`` and its ``doesOneThing`` method, but the
|
||||
problem is that it calls on ``BigParentClass::doesEverything()``. One way to
|
||||
handle this would be to mock out **all** of the dependencies ``BigParentClass``
|
||||
has and needs, and then finally actually test our ``doesOneThing`` method. It's
|
||||
an awful lot of work to do that.
|
||||
|
||||
What we can do, is to do something... unconventional. We can create a runtime
|
||||
partial test double of the ``ChildClass`` itself and mock only the parent's
|
||||
``doesEverything()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$childClass = \Mockery::mock('ChildClass')->makePartial();
|
||||
$childClass->shouldReceive('doesEverything')
|
||||
->andReturn('some result from parent');
|
||||
|
||||
$childClass->doesOneThing(); // string("some result from parent");
|
||||
|
||||
With this approach we mock out only the ``doesEverything()`` method, and all the
|
||||
unmocked methods are called on the actual ``ChildClass`` instance.
|
||||
183
vendor/mockery/mockery/docs/cookbook/class_constants.rst
vendored
Normal file
183
vendor/mockery/mockery/docs/cookbook/class_constants.rst
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
.. index::
|
||||
single: Cookbook; Class Constants
|
||||
|
||||
Class Constants
|
||||
===============
|
||||
|
||||
When creating a test double for a class, Mockery does not create stubs out of
|
||||
any class constants defined in the class we are mocking. Sometimes though, the
|
||||
non-existence of these class constants, setup of the test, and the application
|
||||
code itself, it can lead to undesired behavior, and even a PHP error:
|
||||
``PHP Fatal error: Uncaught Error: Undefined class constant 'FOO' in ...``
|
||||
|
||||
While supporting class constants in Mockery would be possible, it does require
|
||||
an awful lot of work, for a small number of use cases.
|
||||
|
||||
Named Mocks
|
||||
-----------
|
||||
|
||||
We can, however, deal with these constants in a way supported by Mockery - by
|
||||
using :ref:`creating-test-doubles-named-mocks`.
|
||||
|
||||
A named mock is a test double that has a name of the class we want to mock, but
|
||||
under it is a stubbed out class that mimics the real class with canned responses.
|
||||
|
||||
Lets look at the following made up, but not impossible scenario:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Fetcher
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
|
||||
public static function fetch()
|
||||
{
|
||||
// Fetcher gets something for us from somewhere...
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public function doFetching()
|
||||
{
|
||||
$response = Fetcher::fetch();
|
||||
|
||||
if ($response == Fetcher::SUCCESS) {
|
||||
echo "Thanks!" . PHP_EOL;
|
||||
} else {
|
||||
echo "Try again!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Our ``MyClass`` calls a ``Fetcher`` that fetches some resource from somewhere -
|
||||
maybe it downloads a file from a remote web service. Our ``MyClass`` prints out
|
||||
a response message depending on the response from the ``Fetcher::fetch()`` call.
|
||||
|
||||
When testing ``MyClass`` we don't really want ``Fetcher`` to go and download
|
||||
random stuff from the internet every time we run our test suite. So we mock it
|
||||
out:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Using alias: because fetch is called statically!
|
||||
\Mockery::mock('alias:Fetcher')
|
||||
->shouldReceive('fetch')
|
||||
->andReturn(0);
|
||||
|
||||
$myClass = new MyClass();
|
||||
$myClass->doFetching();
|
||||
|
||||
If we run this, our test will error out with a nasty
|
||||
``PHP Fatal error: Uncaught Error: Undefined class constant 'SUCCESS' in ..``.
|
||||
|
||||
Here's how a ``namedMock()`` can help us in a situation like this.
|
||||
|
||||
We create a stub for the ``Fetcher`` class, stubbing out the class constants,
|
||||
and then use ``namedMock()`` to create a mock named ``Fetcher`` based on our
|
||||
stub:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class FetcherStub
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
}
|
||||
|
||||
\Mockery::namedMock('Fetcher', 'FetcherStub')
|
||||
->shouldReceive('fetch')
|
||||
->andReturn(0);
|
||||
|
||||
$myClass = new MyClass();
|
||||
$myClass->doFetching();
|
||||
|
||||
This works because under the hood, Mockery creates a class called ``Fetcher``
|
||||
that extends ``FetcherStub``.
|
||||
|
||||
The same approach will work even if ``Fetcher::fetch()`` is not a static
|
||||
dependency:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Fetcher
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
|
||||
public function fetch()
|
||||
{
|
||||
// Fetcher gets something for us from somewhere...
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public function doFetching($fetcher)
|
||||
{
|
||||
$response = $fetcher->fetch();
|
||||
|
||||
if ($response == Fetcher::SUCCESS) {
|
||||
echo "Thanks!" . PHP_EOL;
|
||||
} else {
|
||||
echo "Try again!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
And the test will have something like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class FetcherStub
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
}
|
||||
|
||||
$mock = \Mockery::mock('Fetcher', 'FetcherStub')
|
||||
$mock->shouldReceive('fetch')
|
||||
->andReturn(0);
|
||||
|
||||
$myClass = new MyClass();
|
||||
$myClass->doFetching($mock);
|
||||
|
||||
|
||||
Constants Map
|
||||
-------------
|
||||
|
||||
Another way of mocking class constants can be with the use of the constants map configuration.
|
||||
|
||||
Given a class with constants:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Fetcher
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
|
||||
public function fetch()
|
||||
{
|
||||
// Fetcher gets something for us from somewhere...
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
It can be mocked with:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->setConstantsMap([
|
||||
'Fetcher' => [
|
||||
'SUCCESS' => 'success',
|
||||
'FAILURE' => 'fail',
|
||||
]
|
||||
]);
|
||||
|
||||
$mock = \Mockery::mock('Fetcher');
|
||||
var_dump($mock::SUCCESS); // (string) 'success'
|
||||
var_dump($mock::FAILURE); // (string) 'fail'
|
||||
@@ -6,6 +6,11 @@ Cookbook
|
||||
|
||||
default_expectations
|
||||
detecting_mock_objects
|
||||
not_calling_the_constructor
|
||||
mocking_hard_dependencies
|
||||
class_constants
|
||||
big_parent_class
|
||||
mockery_on
|
||||
mocking_class_within_class
|
||||
|
||||
.. include:: map.rst.inc
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
* :doc:`/cookbook/default_expectations`
|
||||
* :doc:`/cookbook/detecting_mock_objects`
|
||||
* :doc:`/cookbook/not_calling_the_constructor`
|
||||
* :doc:`/cookbook/mocking_hard_dependencies`
|
||||
* :doc:`/cookbook/class_constants`
|
||||
* :doc:`/cookbook/big_parent_class`
|
||||
* :doc:`/cookbook/mockery_on`
|
||||
|
||||
85
vendor/mockery/mockery/docs/cookbook/mockery_on.rst
vendored
Normal file
85
vendor/mockery/mockery/docs/cookbook/mockery_on.rst
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
.. index::
|
||||
single: Cookbook; Complex Argument Matching With Mockery::on
|
||||
|
||||
Complex Argument Matching With Mockery::on
|
||||
==========================================
|
||||
|
||||
When we need to do a more complex argument matching for an expected method call,
|
||||
the ``\Mockery::on()`` matcher comes in really handy. It accepts a closure as an
|
||||
argument and that closure in turn receives the argument passed in to the method,
|
||||
when called. If the closure returns ``true``, Mockery will consider that the
|
||||
argument has passed the expectation. If the closure returns ``false``, or a
|
||||
"falsey" value, the expectation will not pass.
|
||||
|
||||
The ``\Mockery::on()`` matcher can be used in various scenarios — validating
|
||||
an array argument based on multiple keys and values, complex string matching...
|
||||
|
||||
Say, for example, we have the following code. It doesn't do much; publishes a
|
||||
post by setting the ``published`` flag in the database to ``1`` and sets the
|
||||
``published_at`` to the current date and time:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
namespace Service;
|
||||
class Post
|
||||
{
|
||||
public function __construct($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function publishPost($id)
|
||||
{
|
||||
$saveData = [
|
||||
'post_id' => $id,
|
||||
'published' => 1,
|
||||
'published_at' => gmdate('Y-m-d H:i:s'),
|
||||
];
|
||||
$this->model->save($saveData);
|
||||
}
|
||||
}
|
||||
|
||||
In a test we would mock the model and set some expectations on the call of the
|
||||
``save()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$postId = 42;
|
||||
|
||||
$modelMock = \Mockery::mock('Model');
|
||||
$modelMock->shouldReceive('save')
|
||||
->once()
|
||||
->with(\Mockery::on(function ($argument) use ($postId) {
|
||||
$postIdIsSet = isset($argument['post_id']) && $argument['post_id'] === $postId;
|
||||
$publishedFlagIsSet = isset($argument['published']) && $argument['published'] === 1;
|
||||
$publishedAtIsSet = isset($argument['published_at']);
|
||||
|
||||
return $postIdIsSet && $publishedFlagIsSet && $publishedAtIsSet;
|
||||
}));
|
||||
|
||||
$service = new \Service\Post($modelMock);
|
||||
$service->publishPost($postId);
|
||||
|
||||
\Mockery::close();
|
||||
|
||||
The important part of the example is inside the closure we pass to the
|
||||
``\Mockery::on()`` matcher. The ``$argument`` is actually the ``$saveData`` argument
|
||||
the ``save()`` method gets when it is called. We check for a couple of things in
|
||||
this argument:
|
||||
|
||||
* the post ID is set, and is same as the post ID we passed in to the
|
||||
``publishPost()`` method,
|
||||
* the ``published`` flag is set, and is ``1``, and
|
||||
* the ``published_at`` key is present.
|
||||
|
||||
If any of these requirements is not satisfied, the closure will return ``false``,
|
||||
the method call expectation will not be met, and Mockery will throw a
|
||||
``NoMatchingExpectationException``.
|
||||
|
||||
.. note::
|
||||
|
||||
This cookbook entry is an adaption of the blog post titled
|
||||
`"Complex argument matching in Mockery" <https://robertbasic.com/blog/complex-argument-matching-in-mockery/>`_,
|
||||
published by Robert Basic on his blog.
|
||||
146
vendor/mockery/mockery/docs/cookbook/mocking_class_within_class.rst
vendored
Normal file
146
vendor/mockery/mockery/docs/cookbook/mocking_class_within_class.rst
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
.. index::
|
||||
single: Cookbook; Mocking class within class
|
||||
|
||||
.. _mocking-class-within-class:
|
||||
|
||||
Mocking class within class
|
||||
==========================
|
||||
|
||||
Imagine a case where you need to create an instance of a class and use it
|
||||
within the same method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Point.php
|
||||
<?php
|
||||
namespace App;
|
||||
|
||||
class Point {
|
||||
public function setPoint($x, $y) {
|
||||
echo "Point (" . $x . ", " . $y . ")" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// Rectangle.php
|
||||
<?php
|
||||
namespace App;
|
||||
use App\Point;
|
||||
|
||||
class Rectangle {
|
||||
public function create($x1, $y1, $x2, $y2) {
|
||||
$a = new Point();
|
||||
$a->setPoint($x1, $y1);
|
||||
|
||||
$b = new Point();
|
||||
$b->setPoint($x2, $y1);
|
||||
|
||||
$c = new Point();
|
||||
$c->setPoint($x2, $y2);
|
||||
|
||||
$d = new Point();
|
||||
$d->setPoint($x1, $y2);
|
||||
|
||||
$this->draw([$a, $b, $c, $d]);
|
||||
}
|
||||
|
||||
public function draw($points) {
|
||||
echo "Do something with the points";
|
||||
}
|
||||
}
|
||||
|
||||
And that you want to test that a logic in ``Rectangle->create()`` calls
|
||||
properly each used thing - in this case calls ``Point->setPoint()``, but
|
||||
``Rectangle->draw()`` does some graphical stuff that you want to avoid calling.
|
||||
|
||||
You set the mocks for ``App\Point`` and ``App\Rectangle``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class MyTest extends PHPUnit\Framework\TestCase {
|
||||
public function testCreate() {
|
||||
$point = Mockery::mock("App\Point");
|
||||
// check if our mock is called
|
||||
$point->shouldReceive("setPoint")->andThrow(Exception::class);
|
||||
|
||||
$rect = Mockery::mock("App\Rectangle")->makePartial();
|
||||
$rect->shouldReceive("draw");
|
||||
|
||||
$rect->create(0, 0, 100, 100); // does not throw exception
|
||||
Mockery::close();
|
||||
}
|
||||
}
|
||||
|
||||
and the test does not work. Why? The mocking relies on the class not being
|
||||
present yet, but the class is autoloaded therefore the mock alone for
|
||||
``App\Point`` is useless which you can see with ``echo`` being executed.
|
||||
|
||||
Mocks however work for the first class in the order of loading i.e.
|
||||
``App\Rectangle``, which loads the ``App\Point`` class. In more complex example
|
||||
that would be a single point that initiates the whole loading (``use Class``)
|
||||
such as::
|
||||
|
||||
A // main loading initiator
|
||||
|- B // another loading initiator
|
||||
| |-E
|
||||
| +-G
|
||||
|
|
||||
|- C // another loading initiator
|
||||
| +-F
|
||||
|
|
||||
+- D
|
||||
|
||||
That basically means that the loading prevents mocking and for each such
|
||||
a loading initiator there needs to be implemented a workaround.
|
||||
Overloading is one approach, however it pollutes the global state. In this case
|
||||
we try to completely avoid the global state pollution with custom
|
||||
``new Class()`` behavior per loading initiator and that can be mocked easily
|
||||
in few critical places.
|
||||
|
||||
That being said, although we can't stop loading, we can return mocks. Let's
|
||||
look at ``Rectangle->create()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Rectangle {
|
||||
public function newPoint() {
|
||||
return new Point();
|
||||
}
|
||||
|
||||
public function create($x1, $y1, $x2, $y2) {
|
||||
$a = $this->newPoint();
|
||||
$a->setPoint($x1, $y1);
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
We create a custom function to encapsulate ``new`` keyword that would otherwise
|
||||
just use the autoloaded class ``App\Point`` and in our test we mock that function
|
||||
so that it returns our mock:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class MyTest extends PHPUnit\Framework\TestCase {
|
||||
public function testCreate() {
|
||||
$point = Mockery::mock("App\Point");
|
||||
// check if our mock is called
|
||||
$point->shouldReceive("setPoint")->andThrow(Exception::class);
|
||||
|
||||
$rect = Mockery::mock("App\Rectangle")->makePartial();
|
||||
$rect->shouldReceive("draw");
|
||||
|
||||
// pass the App\Point mock into App\Rectangle as an alternative
|
||||
// to using new App\Point() in-place.
|
||||
$rect->shouldReceive("newPoint")->andReturn($point);
|
||||
|
||||
$this->expectException(Exception::class);
|
||||
$rect->create(0, 0, 100, 100);
|
||||
Mockery::close();
|
||||
}
|
||||
}
|
||||
|
||||
If we run this test now, it should pass. For more complex cases we'd find
|
||||
the next loader in the program flow and proceed with wrapping and passing
|
||||
mock instances with predefined behavior into already existing classes.
|
||||
@@ -16,7 +16,7 @@ Let's take the following code for an example:
|
||||
{
|
||||
function callExternalService($param)
|
||||
{
|
||||
$externalService = new Service\External();
|
||||
$externalService = new Service\External($version = 5);
|
||||
$externalService->sendSomething($param);
|
||||
return $externalService->getSomething();
|
||||
}
|
||||
@@ -91,3 +91,47 @@ Our test example from above now becomes:
|
||||
$this->assertSame('Tested!', $result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Testing the constructor arguments of hard Dependencies
|
||||
------------------------------------------------------
|
||||
|
||||
Sometimes we might want to ensure that the hard dependency is instantiated with
|
||||
particular arguments. With overloaded mocks, we can set up expectations on the
|
||||
constructor.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
namespace AppTest;
|
||||
use Mockery as m;
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
*/
|
||||
class ServiceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCallingExternalService()
|
||||
{
|
||||
$externalMock = m::mock('overload:App\Service\External');
|
||||
$externalMock->allows('sendSomething');
|
||||
$externalMock->shouldReceive('__construct')
|
||||
->once()
|
||||
->with(5);
|
||||
|
||||
$service = new \App\Service();
|
||||
$result = $service->callExternalService($param);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. note::
|
||||
For more straightforward and single-process tests oriented way check
|
||||
:ref:`mocking-class-within-class`.
|
||||
|
||||
.. note::
|
||||
|
||||
This cookbook entry is an adaption of the blog post titled
|
||||
`"Mocking hard dependencies with Mockery" <https://robertbasic.com/blog/mocking-hard-dependencies-with-mockery/>`_,
|
||||
published by Robert Basic on his blog.
|
||||
|
||||
63
vendor/mockery/mockery/docs/cookbook/not_calling_the_constructor.rst
vendored
Normal file
63
vendor/mockery/mockery/docs/cookbook/not_calling_the_constructor.rst
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
.. index::
|
||||
single: Cookbook; Not Calling the Original Constructor
|
||||
|
||||
Not Calling the Original Constructor
|
||||
====================================
|
||||
|
||||
When creating generated partial test doubles, Mockery mocks out only the method
|
||||
which we specifically told it to. This means that the original constructor of
|
||||
the class we are mocking will be called.
|
||||
|
||||
In some cases this is not a desired behavior, as the constructor might issue
|
||||
calls to other methods, or other object collaborators, and as such, can create
|
||||
undesired side-effects in the application's environment when running the tests.
|
||||
|
||||
If this happens, we need to use runtime partial test doubles, as they don't
|
||||
call the original constructor.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
echo "Original constructor called." . PHP_EOL;
|
||||
// Other side-effects can happen...
|
||||
}
|
||||
}
|
||||
|
||||
// This will print "Original constructor called."
|
||||
$mock = \Mockery::mock('MyClass[foo]');
|
||||
|
||||
A better approach is to use runtime partial doubles:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
echo "Original constructor called." . PHP_EOL;
|
||||
// Other side-effects can happen...
|
||||
}
|
||||
}
|
||||
|
||||
// This will not print anything
|
||||
$mock = \Mockery::mock('MyClass')->makePartial();
|
||||
$mock->shouldReceive('foo');
|
||||
|
||||
This is one of the reason why we don't recommend using generated partial test
|
||||
doubles, but if possible, always use the runtime partials.
|
||||
|
||||
Read more about :ref:`creating-test-doubles-partial-test-doubles`.
|
||||
|
||||
.. note::
|
||||
|
||||
The way generated partial test doubles work, is a BC break. If you use a
|
||||
really old version of Mockery, it might behave in a way that the constructor
|
||||
is not being called for these generated partials. In the case if you upgrade
|
||||
to a more recent version of Mockery, you'll probably have to change your
|
||||
tests to use runtime partials, instead of generated ones.
|
||||
|
||||
This change was introduced in early 2013, so it is highly unlikely that you
|
||||
are using a Mockery from before that, so this should not be an issue.
|
||||
@@ -7,5 +7,6 @@ Getting Started
|
||||
installation
|
||||
upgrading
|
||||
simple_example
|
||||
quick_reference
|
||||
|
||||
.. include:: map.rst.inc
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
Mockery can be installed using Composer, PEAR or by cloning it from its GitHub
|
||||
repository. These three options are outlined below.
|
||||
Mockery can be installed using Composer or by cloning it from its GitHub
|
||||
repository. These two options are outlined below.
|
||||
|
||||
Composer
|
||||
--------
|
||||
@@ -35,17 +35,11 @@ To install, you then may call:
|
||||
This will install Mockery as a development dependency, meaning it won't be
|
||||
installed when using ``php composer.phar update --no-dev`` in production.
|
||||
|
||||
PEAR
|
||||
----
|
||||
|
||||
Mockery is hosted on the `survivethedeepend.com <http://pear.survivethedeepend.com>`_
|
||||
PEAR channel and can be installed using the following commands:
|
||||
Other way to install is directly from composer command line, as below.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo pear channel-discover pear.survivethedeepend.com
|
||||
sudo pear channel-discover hamcrest.googlecode.com/svn/pear
|
||||
sudo pear install --alldeps deepend/Mockery
|
||||
php composer.phar require --dev mockery/mockery
|
||||
|
||||
Git
|
||||
---
|
||||
@@ -53,16 +47,3 @@ Git
|
||||
The Git repository hosts the development version in its master branch. You can
|
||||
install this using Composer by referencing ``dev-master`` as your preferred
|
||||
version in your project's ``composer.json`` file as the earlier example shows.
|
||||
|
||||
You may also install this development version using PEAR:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone git://github.com/padraic/mockery.git
|
||||
cd mockery
|
||||
sudo pear channel-discover hamcrest.googlecode.com/svn/pear
|
||||
sudo pear install --alldeps package.xml
|
||||
|
||||
The above processes will install both Mockery and Hamcrest. While omitting
|
||||
Hamcrest will not break Mockery, Hamcrest is recommended as it adds a wider
|
||||
variety of functionality for argument matching.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* :doc:`/getting_started/installation`
|
||||
* :doc:`/getting_started/upgrading`
|
||||
* :doc:`/getting_started/simple_example`
|
||||
* :doc:`/getting_started/quick_reference`
|
||||
|
||||
200
vendor/mockery/mockery/docs/getting_started/quick_reference.rst
vendored
Normal file
200
vendor/mockery/mockery/docs/getting_started/quick_reference.rst
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
.. index::
|
||||
single: Quick Reference
|
||||
|
||||
Quick Reference
|
||||
===============
|
||||
|
||||
The purpose of this page is to give a quick and short overview of some of the
|
||||
most common Mockery features.
|
||||
|
||||
Do read the :doc:`../reference/index` to learn about all the Mockery features.
|
||||
|
||||
Integrate Mockery with PHPUnit, either by extending the ``MockeryTestCase``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class MyTest extends MockeryTestCase
|
||||
{
|
||||
}
|
||||
|
||||
or by using the ``MockeryPHPUnitIntegration`` trait:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \PHPUnit\Framework\TestCase;
|
||||
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
||||
|
||||
class MyTest extends TestCase
|
||||
{
|
||||
use MockeryPHPUnitIntegration;
|
||||
}
|
||||
|
||||
Creating a test double:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$testDouble = \Mockery::mock('MyClass');
|
||||
|
||||
Creating a test double that implements a certain interface:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$testDouble = \Mockery::mock('MyClass, MyInterface');
|
||||
|
||||
Expecting a method to be called on a test double:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$testDouble = \Mockery::mock('MyClass');
|
||||
$testDouble->shouldReceive('foo');
|
||||
|
||||
Expecting a method to **not** be called on a test double:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$testDouble = \Mockery::mock('MyClass');
|
||||
$testDouble->shouldNotReceive('foo');
|
||||
|
||||
Expecting a method to be called on a test double, once, with a certain argument,
|
||||
and to return a value:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->once()
|
||||
->with($arg)
|
||||
->andReturn($returnValue);
|
||||
|
||||
Expecting a method to be called on a test double and to return a different value
|
||||
for each successive call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->andReturn(1, 2, 3);
|
||||
|
||||
$mock->foo(); // int(1);
|
||||
$mock->foo(); // int(2);
|
||||
$mock->foo(); // int(3);
|
||||
$mock->foo(); // int(3);
|
||||
|
||||
Creating a runtime partial test double:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass')->makePartial();
|
||||
|
||||
Creating a spy:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy = \Mockery::spy('MyClass');
|
||||
|
||||
Expecting that a spy should have received a method call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy = \Mockery::spy('MyClass');
|
||||
|
||||
$spy->foo();
|
||||
|
||||
$spy->shouldHaveReceived()->foo();
|
||||
|
||||
Not so simple examples
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Creating a mock object to return a sequence of values from a set of method
|
||||
calls:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class SimpleTest extends MockeryTestCase
|
||||
{
|
||||
public function testSimpleMock()
|
||||
{
|
||||
$mock = \Mockery::mock(array('pi' => 3.1416, 'e' => 2.71));
|
||||
$this->assertEquals(3.1416, $mock->pi());
|
||||
$this->assertEquals(2.71, $mock->e());
|
||||
}
|
||||
}
|
||||
|
||||
Creating a mock object which returns a self-chaining Undefined object for a
|
||||
method call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class UndefinedTest extends MockeryTestCase
|
||||
{
|
||||
public function testUndefinedValues()
|
||||
{
|
||||
$mock = \Mockery::mock('mymock');
|
||||
$mock->shouldReceive('divideBy')->with(0)->andReturnUndefined();
|
||||
$this->assertTrue($mock->divideBy(0) instanceof \Mockery\Undefined);
|
||||
}
|
||||
}
|
||||
|
||||
Creating a mock object with multiple query calls and a single update call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class DbTest extends MockeryTestCase
|
||||
{
|
||||
public function testDbAdapter()
|
||||
{
|
||||
$mock = \Mockery::mock('db');
|
||||
$mock->shouldReceive('query')->andReturn(1, 2, 3);
|
||||
$mock->shouldReceive('update')->with(5)->andReturn(NULL)->once();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
}
|
||||
|
||||
Expecting all queries to be executed before any updates:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class DbTest extends MockeryTestCase
|
||||
{
|
||||
public function testQueryAndUpdateOrder()
|
||||
{
|
||||
$mock = \Mockery::mock('db');
|
||||
$mock->shouldReceive('query')->andReturn(1, 2, 3)->ordered();
|
||||
$mock->shouldReceive('update')->andReturn(NULL)->once()->ordered();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
}
|
||||
|
||||
Creating a mock object where all queries occur after startup, but before finish,
|
||||
and where queries are expected with several different params:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery\Adapter\Phpunit\MockeryTestCase;
|
||||
|
||||
class DbTest extends MockeryTestCase
|
||||
{
|
||||
public function testOrderedQueries()
|
||||
{
|
||||
$db = \Mockery::mock('db');
|
||||
$db->shouldReceive('startup')->once()->ordered();
|
||||
$db->shouldReceive('query')->with('CPWR')->andReturn(12.3)->once()->ordered('queries');
|
||||
$db->shouldReceive('query')->with('MSFT')->andReturn(10.0)->once()->ordered('queries');
|
||||
$db->shouldReceive('query')->with(\Mockery::pattern("/^....$/"))->andReturn(3.3)->atLeast()->once()->ordered('queries');
|
||||
$db->shouldReceive('finish')->once()->ordered();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
}
|
||||
@@ -14,21 +14,21 @@ interaction with the ``Temperature`` class:
|
||||
|
||||
class Temperature
|
||||
{
|
||||
private $service;
|
||||
|
||||
public function __construct($service)
|
||||
{
|
||||
$this->_service = $service;
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
public function average()
|
||||
{
|
||||
$total = 0;
|
||||
for ($i=0;$i<3;$i++) {
|
||||
$total += $this->_service->readTemp();
|
||||
for ($i=0; $i<3; $i++) {
|
||||
$total += $this->service->readTemp();
|
||||
}
|
||||
return $total/3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Even without an actual service class, we can see how we expect it to operate.
|
||||
@@ -38,28 +38,32 @@ mock object for the real service which allows us to test the behaviour of the
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
use \Mockery;
|
||||
|
||||
class TemperatureTest extends PHPUnit_Framework_TestCase
|
||||
class TemperatureTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
Mockery::close();
|
||||
}
|
||||
|
||||
public function testGetsAverageTemperatureFromThreeServiceReadings()
|
||||
{
|
||||
$service = m::mock('service');
|
||||
$service->shouldReceive('readTemp')->times(3)->andReturn(10, 12, 14);
|
||||
$service = Mockery::mock('service');
|
||||
$service->shouldReceive('readTemp')
|
||||
->times(3)
|
||||
->andReturn(10, 12, 14);
|
||||
|
||||
$temperature = new Temperature($service);
|
||||
|
||||
$this->assertEquals(12, $temperature->average());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
We create a mock object which our ``Temperature`` class will use and set some
|
||||
expectations for that mock — that it should receive three calls to the ``readTemp``
|
||||
method, and these calls will return 10, 12, and 14 as results.
|
||||
|
||||
.. note::
|
||||
|
||||
PHPUnit integration can remove the need for a ``tearDown()`` method. See
|
||||
|
||||
@@ -4,11 +4,67 @@
|
||||
Upgrading
|
||||
=========
|
||||
|
||||
Upgrading to 1.0.0
|
||||
------------------
|
||||
|
||||
Minimum PHP version
|
||||
+++++++++++++++++++
|
||||
|
||||
As of Mockery 1.0.0 the minimum PHP version required is 5.6.
|
||||
|
||||
Using Mockery with PHPUnit
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
In the "old days", 0.9.x and older, the way Mockery was integrated with PHPUnit was
|
||||
through a PHPUnit listener. That listener would in turn call the ``\Mockery::close()``
|
||||
method for us.
|
||||
|
||||
As of 1.0.0, PHPUnit test cases where we want to use Mockery, should either use the
|
||||
``\Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration`` trait, or extend the
|
||||
``\Mockery\Adapter\Phpunit\MockeryTestCase`` test case. This will in turn call the
|
||||
``\Mockery::close()`` method for us.
|
||||
|
||||
Read the documentation for a detailed overview of ":doc:`/reference/phpunit_integration`".
|
||||
|
||||
``\Mockery\Matcher\MustBe`` is deprecated
|
||||
+++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
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
|
||||
MustBe matcher.
|
||||
|
||||
``allows`` and ``expects``
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
As of 1.0.0, Mockery has two new methods to set up expectations: ``allows`` and ``expects``.
|
||||
This means that these methods names are now "reserved" for Mockery, or in other words
|
||||
classes you want to mock with Mockery, can't have methods called ``allows`` or ``expects``.
|
||||
|
||||
Read more in the documentation about this ":doc:`/reference/alternative_should_receive_syntax`".
|
||||
|
||||
No more implicit regex matching for string arguments
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
When setting up string arguments in method expectations, Mockery 0.9.x and older, would try
|
||||
to match arguments using a regular expression in a "last attempt" scenario.
|
||||
|
||||
As of 1.0.0, Mockery will no longer attempt to do this regex matching, but will only try
|
||||
first the identical operator ``===``, and failing that, the equals operator ``==``.
|
||||
|
||||
If you want to match an argument using regular expressions, please use the new
|
||||
``\Mockery\Matcher\Pattern`` matcher. Read more in the documentation about this
|
||||
pattern matcher in the ":doc:`/reference/argument_validation`" section.
|
||||
|
||||
``andThrow`` ``\Throwable``
|
||||
+++++++++++++++++++++++++++
|
||||
|
||||
As of 1.0.0, the ``andThrow`` can now throw any ``\Throwable``.
|
||||
|
||||
Upgrading to 0.9
|
||||
----------------
|
||||
|
||||
The generator was completely rewritten, so any code with a deep integration to
|
||||
mockery will need evaluating
|
||||
mockery will need evaluating.
|
||||
|
||||
Upgrading to 0.8
|
||||
----------------
|
||||
@@ -18,7 +74,7 @@ Since the release of 0.8.0 the following behaviours were altered:
|
||||
1. The ``shouldIgnoreMissing()`` behaviour optionally applied to mock objects
|
||||
returned an instance of ``\Mockery\Undefined`` when methods called did not
|
||||
match a known expectation. Since 0.8.0, this behaviour was switched to
|
||||
returning ``null`` instead. You can restore the 0.7.2 behavour by using the
|
||||
returning ``null`` instead. You can restore the 0.7.2 behaviour by using the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
12
vendor/mockery/mockery/docs/index.rst
vendored
12
vendor/mockery/mockery/docs/index.rst
vendored
@@ -50,6 +50,18 @@ framework.
|
||||
|
||||
.. include:: reference/map.rst.inc
|
||||
|
||||
Mockery
|
||||
-------
|
||||
|
||||
Learn about Mockery's configuration, reserved method names, exceptions...
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
mockery/index
|
||||
|
||||
.. include:: mockery/map.rst.inc
|
||||
|
||||
Cookbook
|
||||
--------
|
||||
|
||||
|
||||
94
vendor/mockery/mockery/docs/mockery/configuration.rst
vendored
Normal file
94
vendor/mockery/mockery/docs/mockery/configuration.rst
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
.. index::
|
||||
single: Mockery; Configuration
|
||||
|
||||
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 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
|
||||
non-existent methods may allow mocks based on real classes/objects to fall out
|
||||
of sync with the actual implementations, especially when some degree of
|
||||
integration testing (testing of object wiring) is not being performed.
|
||||
|
||||
You may allow or disallow this behaviour (whether for whole test suites or
|
||||
just select tests) by using the following call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->allowMockingNonExistentMethods(bool);
|
||||
|
||||
Passing a true allows the behaviour, false disallows it. It takes effect
|
||||
immediately until switched back. If the behaviour is detected when not allowed,
|
||||
it will result in an Exception being thrown at that point. Note that disallowing
|
||||
this behaviour should be carefully considered since it necessarily removes at
|
||||
least some of Mockery's flexibility.
|
||||
|
||||
The other two methods are:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->setInternalClassMethodParamMap($class, $method, array $paramMap)
|
||||
\Mockery::getConfiguration()->getInternalClassMethodParamMap($class, $method)
|
||||
|
||||
These are used to define parameters (i.e. the signature string of each) for the
|
||||
methods of internal PHP classes (e.g. SPL, or PECL extension classes like
|
||||
ext/mongo's MongoCollection. Reflection cannot analyse the parameters of internal
|
||||
classes. Most of the time, you never need to do this. It's mainly needed where an
|
||||
internal class method uses pass-by-reference for a parameter - you MUST in such
|
||||
cases ensure the parameter signature includes the ``&`` symbol correctly as Mockery
|
||||
won't correctly add it automatically for internal classes. Note that internal class
|
||||
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
|
||||
----------------------------
|
||||
|
||||
Mockery heavily uses `"reflection" <https://secure.php.net/manual/en/book.reflection.php>`_
|
||||
to do it's job. To speed up things, Mockery caches internally the information it
|
||||
gathers via reflection. In some cases, this caching can cause problems.
|
||||
|
||||
The **only** known situation when this occurs is when PHPUnit's ``--static-backup`` option
|
||||
is used. If you use ``--static-backup`` and you get an error that looks like the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
Error: Internal error: Failed to retrieve the reflection object
|
||||
|
||||
We suggest turning off the reflection cache as so:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->disableReflectionCache();
|
||||
|
||||
Turning it back on can be done like so:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->enableReflectionCache();
|
||||
|
||||
In no other situation should you be required turn this reflection cache off.
|
||||
@@ -14,21 +14,15 @@ so it can be documented and resolved where possible. Here is a list to note:
|
||||
expectations set for it. This is necessary since Mockery must serialize and
|
||||
unserialize objects to avoid some ``__construct()`` insanity and attempting
|
||||
to mock a ``__wakeup()`` method as normal leads to a
|
||||
``BadMethodCallException`` been thrown.
|
||||
``BadMethodCallException`` being thrown.
|
||||
|
||||
2. Classes using non-real methods, i.e. where a method call triggers a
|
||||
``__call()`` method, will throw an exception that the non-real method does
|
||||
not exist unless you first define at least one expectation (a simple
|
||||
``shouldReceive()`` call would suffice). This is necessary since there is
|
||||
no other way for Mockery to be aware of the method name.
|
||||
|
||||
3. Mockery has two scenarios where real classes are replaced: Instance mocks
|
||||
2. Mockery has two scenarios where real classes are replaced: Instance mocks
|
||||
and alias mocks. Both will generate PHP fatal errors if the real class is
|
||||
loaded, usually via a require or include statement. Only use these two mock
|
||||
types where autoloading is in place and where classes are not explicitly
|
||||
loaded on a per-file basis using ``require()``, ``require_once()``, etc.
|
||||
|
||||
4. Internal PHP classes are not entirely capable of being fully analysed using
|
||||
3. Internal PHP classes are not entirely capable of being fully analysed using
|
||||
``Reflection``. For example, ``Reflection`` cannot reveal details of
|
||||
expected parameters to the methods of such internal classes. As a result,
|
||||
there will be problems where a method parameter is defined to accept a
|
||||
@@ -36,6 +30,14 @@ so it can be documented and resolved where possible. Here is a list to note:
|
||||
pass by value on scalars and arrays). If references as internal class
|
||||
method parameters are needed, you should use the
|
||||
``\Mockery\Configuration::setInternalClassMethodParamMap()`` method.
|
||||
Note, however that internal class parameter overriding is not available in
|
||||
PHP 8 since incompatible signatures have been reclassified as fatal errors.
|
||||
|
||||
4. Creating a mock implementing a certain interface with incorrect case in the
|
||||
interface name, and then creating a second mock implementing the same
|
||||
interface, but this time with the correct case, will have undefined behavior
|
||||
due to PHP's ``class_exists`` and related functions being case insensitive.
|
||||
Using the ``::class`` keyword in PHP can help you avoid these mistakes.
|
||||
|
||||
The gotchas noted above are largely down to PHP's architecture and are assumed
|
||||
to be unavoidable. But - if you figure out a solution (or a better one than
|
||||
@@ -2,9 +2,11 @@ Mockery
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
|
||||
configuration
|
||||
exceptions
|
||||
reserved_method_names
|
||||
gotchas
|
||||
|
||||
.. include:: map.rst.inc
|
||||
4
vendor/mockery/mockery/docs/mockery/map.rst.inc
vendored
Normal file
4
vendor/mockery/mockery/docs/mockery/map.rst.inc
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
* :doc:`/mockery/configuration`
|
||||
* :doc:`/mockery/exceptions`
|
||||
* :doc:`/mockery/reserved_method_names`
|
||||
* :doc:`/mockery/gotchas`
|
||||
@@ -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
|
||||
91
vendor/mockery/mockery/docs/reference/alternative_should_receive_syntax.rst
vendored
Normal file
91
vendor/mockery/mockery/docs/reference/alternative_should_receive_syntax.rst
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
.. index::
|
||||
single: Alternative shouldReceive Syntax
|
||||
|
||||
Alternative shouldReceive Syntax
|
||||
================================
|
||||
|
||||
As of Mockery 1.0.0, we support calling methods as we would call any PHP method,
|
||||
and not as string arguments to Mockery ``should*`` methods.
|
||||
|
||||
The two Mockery methods that enable this are ``allows()`` and ``expects()``.
|
||||
|
||||
Allows
|
||||
------
|
||||
|
||||
We use ``allows()`` when we create stubs for methods that return a predefined
|
||||
return value, but for these method stubs we don't care how many times, or if at
|
||||
all, were they called.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->allows([
|
||||
'name_of_method_1' => 'return value',
|
||||
'name_of_method_2' => 'return value',
|
||||
]);
|
||||
|
||||
This is equivalent with the following ``shouldReceive`` syntax:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive([
|
||||
'name_of_method_1' => 'return value',
|
||||
'name_of_method_2' => 'return value',
|
||||
]);
|
||||
|
||||
Note that with this format, we also tell Mockery that we don't care about the
|
||||
arguments to the stubbed methods.
|
||||
|
||||
If we do care about the arguments, we would do it like so:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->allows()
|
||||
->name_of_method_1($arg1)
|
||||
->andReturn('return value');
|
||||
|
||||
This is equivalent with the following ``shouldReceive`` syntax:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method_1')
|
||||
->with($arg1)
|
||||
->andReturn('return value');
|
||||
|
||||
Expects
|
||||
-------
|
||||
|
||||
We use ``expects()`` when we want to verify that a particular method was called:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->expects()
|
||||
->name_of_method_1($arg1)
|
||||
->andReturn('return value');
|
||||
|
||||
This is equivalent with the following ``shouldReceive`` syntax:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method_1')
|
||||
->once()
|
||||
->with($arg1)
|
||||
->andReturn('return value');
|
||||
|
||||
By default ``expects()`` sets up an expectation that the method should be called
|
||||
once and once only. If we expect more than one call to the method, we can change
|
||||
that expectation:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->expects()
|
||||
->name_of_method_1($arg1)
|
||||
->twice()
|
||||
->andReturn('return value');
|
||||
|
||||
@@ -6,7 +6,7 @@ Argument Validation
|
||||
|
||||
The arguments passed to the ``with()`` declaration when setting up an
|
||||
expectation determine the criteria for matching method calls to expectations.
|
||||
Thus, you can setup up many expectations for a single method, each
|
||||
Thus, we can setup up many expectations for a single method, each
|
||||
differentiated by the expected arguments. Such argument matching is done on a
|
||||
"best fit" basis. This ensures explicit matches take precedence over
|
||||
generalised matches.
|
||||
@@ -21,148 +21,318 @@ arguments be defined in non-explicit terms, e.g. ``Mockery::any()`` passed to
|
||||
Mockery's generic matchers do not cover all possibilities but offers optional
|
||||
support for the Hamcrest library of matchers. Hamcrest is a PHP port of the
|
||||
similarly named Java library (which has been ported also to Python, Erlang,
|
||||
etc). I strongly recommend using Hamcrest since Mockery simply does not need
|
||||
to duplicate Hamcrest's already impressive utility which itself promotes a
|
||||
natural English DSL.
|
||||
etc). By using Hamcrest, Mockery does not need to duplicate Hamcrest's already
|
||||
impressive utility which itself promotes a natural English DSL.
|
||||
|
||||
The example below show Mockery matchers and their Hamcrest equivalent.
|
||||
Hamcrest uses functions (no namespacing).
|
||||
The examples below show Mockery matchers and their Hamcrest equivalent, if there
|
||||
is one. Hamcrest uses functions (no namespacing).
|
||||
|
||||
Here's a sample of the possibilities.
|
||||
.. note::
|
||||
|
||||
If you don't wish to use the global Hamcrest functions, they are all exposed
|
||||
through the ``\Hamcrest\Matchers`` class as well, as static methods. Thus,
|
||||
``identicalTo($arg)`` is the same as ``\Hamcrest\Matchers::identicalTo($arg)``
|
||||
|
||||
The most common matcher is the ``with()`` matcher:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(1)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(1):
|
||||
|
||||
Matches the integer ``1``. This passes the ``===`` test (identical). It does
|
||||
facilitate a less strict ``==`` check (equals) where the string ``'1'`` would
|
||||
also match the
|
||||
argument.
|
||||
It tells mockery that it should receive a call to the ``foo`` method with the
|
||||
integer ``1`` as an argument. In cases like this, Mockery first tries to match
|
||||
the arguments using ``===`` (identical) comparison operator. If the argument is
|
||||
a primitive, and if it fails the identical comparison, Mockery does a fallback
|
||||
to the ``==`` (equals) comparison operator.
|
||||
|
||||
When matching objects as arguments, Mockery only does the strict ``===``
|
||||
comparison, which means only the same ``$object`` will match:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::any()) OR with(anything())
|
||||
$object = new stdClass();
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->with($object);
|
||||
|
||||
Matches any argument. Basically, anything and everything passed in this
|
||||
argument slot is passed unconstrained.
|
||||
// Hamcrest equivalent
|
||||
$mock->shouldReceive("foo")
|
||||
->with(identicalTo($object));
|
||||
|
||||
A different instance of ``stdClass`` will **not** match.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``Mockery\Matcher\MustBe`` matcher has been deprecated.
|
||||
|
||||
If we need a loose comparison of objects, we can do that using Hamcrest's
|
||||
``equalTo`` matcher:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::type('resource')) OR with(resourceValue()) OR with(typeOf('resource'))
|
||||
$mock->shouldReceive("foo")
|
||||
->with(equalTo(new stdClass));
|
||||
|
||||
Matches any resource, i.e. returns true from an ``is_resource()`` call. The
|
||||
Type matcher accepts any string which can be attached to ``is_`` to form a
|
||||
valid type check. For example, ``\Mockery::type('float')`` or Hamcrest's
|
||||
``floatValue()`` and ``typeOf('float')`` checks using ``is_float()``, and
|
||||
``\Mockery::type('callable')`` or Hamcrest's ``callable()`` uses
|
||||
In cases when we don't care about the type, or the value of an argument, just
|
||||
that any argument is present, we use ``any()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->with(\Mockery::any());
|
||||
|
||||
// Hamcrest equivalent
|
||||
$mock->shouldReceive("foo")
|
||||
->with(anything())
|
||||
|
||||
Anything and everything passed in this argument slot is passed unconstrained.
|
||||
|
||||
Validating Types and Resources
|
||||
------------------------------
|
||||
|
||||
The ``type()`` matcher accepts any string which can be attached to ``is_`` to
|
||||
form a valid type check.
|
||||
|
||||
To match any PHP resource, we could do the following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->with(\Mockery::type('resource'));
|
||||
|
||||
// Hamcrest equivalents
|
||||
$mock->shouldReceive("foo")
|
||||
->with(resourceValue());
|
||||
$mock->shouldReceive("foo")
|
||||
->with(typeOf('resource'));
|
||||
|
||||
It will return a ``true`` from an ``is_resource()`` call, if the provided
|
||||
argument to the method is a PHP resource. For example, ``\Mockery::type('float')``
|
||||
or Hamcrest's ``floatValue()`` and ``typeOf('float')`` checks use ``is_float()``,
|
||||
and ``\Mockery::type('callable')`` or Hamcrest's ``callable()`` uses
|
||||
``is_callable()``.
|
||||
|
||||
The Type matcher also accepts a class or interface name to be used in an
|
||||
``instanceof`` evaluation of the actual argument (similarly Hamcrest uses
|
||||
``anInstanceOf()``).
|
||||
The ``type()`` matcher also accepts a class or interface name to be used in an
|
||||
``instanceof`` evaluation of the actual argument. Hamcrest uses ``anInstanceOf()``.
|
||||
|
||||
You may find a full list of the available type checkers at
|
||||
A full list of the type checkers is available at
|
||||
`php.net <http://www.php.net/manual/en/ref.var.php>`_ or browse Hamcrest's function
|
||||
list in
|
||||
`the Hamcrest code <http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-php/hamcrest/Hamcrest.php>`_.
|
||||
`the Hamcrest code <https://github.com/hamcrest/hamcrest-php/blob/master/hamcrest/Hamcrest.php>`_.
|
||||
|
||||
.. _argument-validation-complex-argument-validation:
|
||||
|
||||
Complex Argument Validation
|
||||
---------------------------
|
||||
|
||||
If we want to perform a complex argument validation, the ``on()`` matcher is
|
||||
invaluable. It accepts a closure (anonymous function) to which the actual
|
||||
argument will be passed.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::on(closure))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->with(\Mockery::on(closure));
|
||||
|
||||
The On matcher accepts a closure (anonymous function) to which the actual
|
||||
argument will be passed. If the closure evaluates to (i.e. returns) boolean
|
||||
``true`` then the argument is assumed to have matched the expectation. This is
|
||||
invaluable where your argument expectation is a bit too complex for or simply
|
||||
not implemented in the current default matchers.
|
||||
|
||||
There is no Hamcrest version of this functionality.
|
||||
If the closure evaluates to (i.e. returns) boolean ``true`` then the argument is
|
||||
assumed to have matched the expectation.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with('/^foo/') OR with(matchesPattern('/^foo/'))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
|
||||
The argument declarator also assumes any given string may be a regular
|
||||
expression to be used against actual arguments when matching. The regex option
|
||||
is only used when a) there is no ``===`` or ``==`` match and b) when the regex
|
||||
is verified to be a valid regex (i.e. does not return false from
|
||||
``preg_match()``). If the regex detection doesn't suit your tastes, Hamcrest
|
||||
offers the more explicit ``matchesPattern()`` function.
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::on(function ($argument) {
|
||||
if ($argument % 2 == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
|
||||
$mock->foo(4); // matches the expectation
|
||||
$mock->foo(3); // throws a NoMatchingExpectationException
|
||||
|
||||
.. note::
|
||||
|
||||
There is no Hamcrest version of the ``on()`` matcher.
|
||||
|
||||
We can also perform argument validation by passing a closure to ``withArgs()``
|
||||
method. The closure will receive all arguments passed in the call to the expected
|
||||
method and if it evaluates (i.e. returns) to boolean ``true``, then the list of
|
||||
arguments is assumed to have matched the expectation:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::ducktype('foo', 'bar'))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->withArgs(closure);
|
||||
|
||||
The Ducktype matcher is an alternative to matching by class type. It simply
|
||||
matches any argument which is an object containing the provided list of
|
||||
The closure can also handle optional parameters, so if an optional parameter is
|
||||
missing in the call to the expected method, it doesn't necessary means that the
|
||||
list of arguments doesn't match the expectation.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$closure = function ($odd, $even, $sum = null) {
|
||||
$result = ($odd % 2 != 0) && ($even % 2 == 0);
|
||||
if (!is_null($sum)) {
|
||||
return $result && ($odd + $even == $sum);
|
||||
}
|
||||
return $result;
|
||||
};
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')->withArgs($closure);
|
||||
|
||||
$mock->foo(1, 2); // It matches the expectation: the optional argument is not needed
|
||||
$mock->foo(1, 2, 3); // It also matches the expectation: the optional argument pass the validation
|
||||
$mock->foo(1, 2, 4); // It doesn't match the expectation: the optional doesn't pass the validation
|
||||
|
||||
.. note::
|
||||
|
||||
In previous versions, Mockery's ``with()`` would attempt to do a pattern
|
||||
matching against the arguments, attempting to use the argument as a
|
||||
regular expression. Over time this proved to be not such a great idea, so
|
||||
we removed this functionality, and have introduced ``Mockery::pattern()``
|
||||
instead.
|
||||
|
||||
If we would like to match an argument against a regular expression, we can use
|
||||
the ``\Mockery::pattern()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::pattern('/^foo/'));
|
||||
|
||||
// Hamcrest equivalent
|
||||
$mock->shouldReceive('foo')
|
||||
->with(matchesPattern('/^foo/'));
|
||||
|
||||
The ``ducktype()`` matcher is an alternative to matching by class type:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::ducktype('foo', 'bar'));
|
||||
|
||||
It matches any argument which is an object containing the provided list of
|
||||
methods to call.
|
||||
|
||||
There is no Hamcrest version of this functionality.
|
||||
.. note::
|
||||
|
||||
There is no Hamcrest version of the ``ducktype()`` matcher.
|
||||
|
||||
Capturing Arguments
|
||||
-------------------
|
||||
|
||||
If we want to perform multiple validations on a single argument, the ``capture``
|
||||
matcher provides a streamlined alternative to using the ``on()`` matcher.
|
||||
It accepts a variable which the actual argument will be assigned.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::mustBe(2)) OR with(identicalTo(2))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive("foo")
|
||||
->with(\Mockery::capture($bar));
|
||||
|
||||
The MustBe matcher is more strict than the default argument matcher. The
|
||||
default matcher allows for PHP type casting, but the MustBe matcher also
|
||||
verifies that the argument must be of the same type as the expected value.
|
||||
Thus by default, the argument `'2'` matches the actual argument 2 (integer)
|
||||
but the MustBe matcher would fail in the same situation since the expected
|
||||
argument was a string and instead we got an integer.
|
||||
This will assign *any* argument passed to ``foo`` to the local ``$bar`` variable to
|
||||
then perform additional validation using assertions.
|
||||
|
||||
Note: Objects are not subject to an identical comparison using this matcher
|
||||
since PHP would fail the comparison if both objects were not the exact same
|
||||
instance. This is a hindrance when objects are generated prior to being
|
||||
returned, since an identical match just would never be possible.
|
||||
.. note::
|
||||
|
||||
The ``capture`` matcher always evaluates to ``true``. As such, we should always
|
||||
perform additional argument validation.
|
||||
|
||||
Additional Argument Matchers
|
||||
----------------------------
|
||||
|
||||
The ``not()`` matcher matches any argument which is not equal or identical to
|
||||
the matcher's parameter:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::not(2)) OR with(not(2))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::not(2));
|
||||
|
||||
The Not matcher matches any argument which is not equal or identical to the
|
||||
matcher's parameter.
|
||||
// Hamcrest equivalent
|
||||
$mock->shouldReceive('foo')
|
||||
->with(not(2));
|
||||
|
||||
``anyOf()`` matches any argument which equals any one of the given parameters:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::anyOf(1, 2)) OR with(anyOf(1,2))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::anyOf(1, 2));
|
||||
|
||||
Matches any argument which equals any one of the given parameters.
|
||||
// Hamcrest equivalent
|
||||
$mock->shouldReceive('foo')
|
||||
->with(anyOf(1,2));
|
||||
|
||||
``notAnyOf()`` matches any argument which is not equal or identical to any of
|
||||
the given parameters:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::notAnyOf(1, 2))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::notAnyOf(1, 2));
|
||||
|
||||
Matches any argument which is not equal or identical to any of the given
|
||||
parameters.
|
||||
.. note::
|
||||
|
||||
There is no Hamcrest version of this functionality.
|
||||
There is no Hamcrest version of the ``notAnyOf()`` matcher.
|
||||
|
||||
``subset()`` matches any argument which is any array containing the given array
|
||||
subset:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::subset(array(0 => 'foo')))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::subset(array(0 => 'foo')));
|
||||
|
||||
Matches any argument which is any array containing the given array subset.
|
||||
This enforces both key naming and values, i.e. both the key and value of each
|
||||
actual element is compared.
|
||||
|
||||
There is no Hamcrest version of this functionality, though Hamcrest can check
|
||||
a single entry using ``hasEntry()`` or ``hasKeyValuePair()``.
|
||||
.. note::
|
||||
|
||||
There is no Hamcrest version of this functionality, though Hamcrest can check
|
||||
a single entry using ``hasEntry()`` or ``hasKeyValuePair()``.
|
||||
|
||||
``contains()`` matches any argument which is an array containing the listed
|
||||
values:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::contains(value1, value2))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::contains(value1, value2));
|
||||
|
||||
Matches any argument which is an array containing the listed values. The
|
||||
naming of keys is ignored.
|
||||
The naming of keys is ignored.
|
||||
|
||||
``hasKey()`` matches any argument which is an array containing the given key
|
||||
name:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::hasKey(key));
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::hasKey(key));
|
||||
|
||||
Matches any argument which is an array containing the given key name.
|
||||
``hasValue()`` matches any argument which is an array containing the given
|
||||
value:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(\Mockery::hasValue(value));
|
||||
|
||||
Matches any argument which is an array containing the given value.
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->with(\Mockery::hasValue(value));
|
||||
|
||||
435
vendor/mockery/mockery/docs/reference/creating_test_doubles.rst
vendored
Normal file
435
vendor/mockery/mockery/docs/reference/creating_test_doubles.rst
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
.. index::
|
||||
single: Reference; Creating Test Doubles
|
||||
|
||||
Creating Test Doubles
|
||||
=====================
|
||||
|
||||
Mockery's main goal is to help us create test doubles. It can create stubs,
|
||||
mocks, and spies.
|
||||
|
||||
Stubs and mocks are created the same. The difference between the two is that a
|
||||
stub only returns a preset result when called, while a mock needs to have
|
||||
expectations set on the method calls it expects to receive.
|
||||
|
||||
Spies are a type of test doubles that keep track of the calls they received, and
|
||||
allow us to inspect these calls after the fact.
|
||||
|
||||
When creating a test double object, we can pass in an identifier as a name for
|
||||
our test double. If we pass it no identifier, the test double name will be
|
||||
unknown. Furthermore, the identifier does not have to be a class name. It is a
|
||||
good practice, and our recommendation, to always name the test doubles with the
|
||||
same name as the underlying class we are creating test doubles for.
|
||||
|
||||
If the identifier we use for our test double is a name of an existing class,
|
||||
the test double will inherit the type of the class (via inheritance), i.e. the
|
||||
mock object will pass type hints or ``instanceof`` evaluations for the existing
|
||||
class. This is useful when a test double must be of a specific type, to satisfy
|
||||
the expectations our code has.
|
||||
|
||||
Stubs and mocks
|
||||
---------------
|
||||
|
||||
Stubs and mocks are created by calling the ``\Mockery::mock()`` method. The
|
||||
following example shows how to create a stub, or a mock, object named "foo":
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('foo');
|
||||
|
||||
The mock object created like this is the loosest form of mocks possible, and is
|
||||
an instance of ``\Mockery\MockInterface``.
|
||||
|
||||
.. note::
|
||||
|
||||
All test doubles created with Mockery are an instance of
|
||||
``\Mockery\MockInterface``, regardless are they a stub, mock or a spy.
|
||||
|
||||
To create a stub or a mock object with no name, we can call the ``mock()``
|
||||
method with no parameters:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock();
|
||||
|
||||
As we stated earlier, we don't recommend creating stub or mock objects without
|
||||
a name.
|
||||
|
||||
Classes, abstracts, interfaces
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The recommended way to create a stub or a mock object is by using a name of
|
||||
an existing class we want to create a test double of:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
|
||||
This stub or mock object will have the type of ``MyClass``, through inheritance.
|
||||
|
||||
Stub or mock objects can be based on any concrete class, abstract class or even
|
||||
an interface. The primary purpose is to ensure the mock object inherits a
|
||||
specific type for type hinting.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyInterface');
|
||||
|
||||
This stub or mock object will implement the ``MyInterface`` interface.
|
||||
|
||||
.. note::
|
||||
|
||||
Classes marked final, or classes that have methods marked final cannot be
|
||||
mocked fully. Mockery supports creating partial mocks for these cases.
|
||||
Partial mocks will be explained later in the documentation.
|
||||
|
||||
Mockery also supports creating stub or mock objects based on a single existing
|
||||
class, which must implement one or more interfaces. We can do this by providing
|
||||
a comma-separated list of the class and interfaces as the first argument to the
|
||||
``\Mockery::mock()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass, MyInterface, OtherInterface');
|
||||
|
||||
This stub or mock object will now be of type ``MyClass`` and implement the
|
||||
``MyInterface`` and ``OtherInterface`` interfaces.
|
||||
|
||||
.. note::
|
||||
|
||||
The class name doesn't need to be the first member of the list but it's a
|
||||
friendly convention to use for readability.
|
||||
|
||||
We can tell a mock to implement the desired interfaces by passing the list of
|
||||
interfaces as the second argument:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass', 'MyInterface, OtherInterface');
|
||||
|
||||
For all intents and purposes, this is the same as the previous example.
|
||||
|
||||
Spies
|
||||
-----
|
||||
|
||||
The third type of test doubles Mockery supports are spies. The main difference
|
||||
between spies and mock objects is that with spies we verify the calls made
|
||||
against our test double after the calls were made. We would use a spy when we
|
||||
don't necessarily care about all of the calls that are going to be made to an
|
||||
object.
|
||||
|
||||
A spy will return ``null`` for all method calls it receives. It is not possible
|
||||
to tell a spy what will be the return value of a method call. If we do that, then
|
||||
we would deal with a mock object, and not with a spy.
|
||||
|
||||
We create a spy by calling the ``\Mockery::spy()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy = \Mockery::spy('MyClass');
|
||||
|
||||
Just as with stubs or mocks, we can tell Mockery to base a spy on any concrete
|
||||
or abstract class, or to implement any number of interfaces:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy = \Mockery::spy('MyClass, MyInterface, OtherInterface');
|
||||
|
||||
This spy will now be of type ``MyClass`` and implement the ``MyInterface`` and
|
||||
``OtherInterface`` interfaces.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``\Mockery::spy()`` method call is actually a shorthand for calling
|
||||
``\Mockery::mock()->shouldIgnoreMissing()``. The ``shouldIgnoreMissing``
|
||||
method is a "behaviour modifier". We'll discuss them a bit later.
|
||||
|
||||
Mocks vs. Spies
|
||||
---------------
|
||||
|
||||
Let's try and illustrate the difference between mocks and spies with the
|
||||
following example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$spy = \Mockery::spy('MyClass');
|
||||
|
||||
$mock->shouldReceive('foo')->andReturn(42);
|
||||
|
||||
$mockResult = $mock->foo();
|
||||
$spyResult = $spy->foo();
|
||||
|
||||
$spy->shouldHaveReceived()->foo();
|
||||
|
||||
var_dump($mockResult); // int(42)
|
||||
var_dump($spyResult); // null
|
||||
|
||||
As we can see from this example, with a mock object we set the call expectations
|
||||
before the call itself, and we get the return result we expect it to return.
|
||||
With a spy object on the other hand, we verify the call has happened after the
|
||||
fact. The return result of a method call against a spy is always ``null``.
|
||||
|
||||
We also have a dedicated chapter to :doc:`spies` only.
|
||||
|
||||
.. _creating-test-doubles-partial-test-doubles:
|
||||
|
||||
Partial Test Doubles
|
||||
--------------------
|
||||
|
||||
Partial doubles are useful when we want to stub out, set expectations for, or
|
||||
spy on *some* methods of a class, but run the actual code for other methods.
|
||||
|
||||
We differentiate between three types of partial test doubles:
|
||||
|
||||
* runtime partial test doubles,
|
||||
* generated partial test doubles, and
|
||||
* proxied partial test doubles.
|
||||
|
||||
Runtime partial test doubles
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
What we call a runtime partial, involves creating a test double and then telling
|
||||
it to make itself partial. Any method calls that the double hasn't been told to
|
||||
allow or expect, will act as they would on a normal instance of the object.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Foo {
|
||||
function foo() { return 123; }
|
||||
function bar() { return $this->foo(); }
|
||||
}
|
||||
|
||||
$foo = mock(Foo::class)->makePartial();
|
||||
$foo->foo(); // int(123);
|
||||
|
||||
We can then tell the test double to allow or expect calls as with any other
|
||||
Mockery double.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$foo->shouldReceive('foo')->andReturn(456);
|
||||
$foo->bar(); // int(456)
|
||||
|
||||
See the cookbook entry on :doc:`../cookbook/big_parent_class` for an example
|
||||
usage of runtime partial test doubles.
|
||||
|
||||
Generated partial test doubles
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The second type of partial double we can create is what we call a generated
|
||||
partial. With generated partials, we specifically tell Mockery which methods
|
||||
we want to be able to allow or expect calls to. All other methods will run the
|
||||
actual code *directly*, so stubs and expectations on these methods will not
|
||||
work.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Foo {
|
||||
function foo() { return 123; }
|
||||
function bar() { return $this->foo(); }
|
||||
}
|
||||
|
||||
$foo = mock("Foo[foo]");
|
||||
|
||||
$foo->foo(); // error, no expectation set
|
||||
|
||||
$foo->shouldReceive('foo')->andReturn(456);
|
||||
$foo->foo(); // int(456)
|
||||
|
||||
// setting an expectation for this has no effect
|
||||
$foo->shouldReceive('bar')->andReturn(999);
|
||||
$foo->bar(); // int(456)
|
||||
|
||||
It's also possible to specify explicitly which methods to run directly using
|
||||
the `!method` syntax:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Foo {
|
||||
function foo() { return 123; }
|
||||
function bar() { return $this->foo(); }
|
||||
}
|
||||
|
||||
$foo = mock("Foo[!foo]");
|
||||
|
||||
$foo->foo(); // int(123)
|
||||
|
||||
$foo->bar(); // error, no expectation set
|
||||
|
||||
.. note::
|
||||
|
||||
Even though we support generated partial test doubles, we do not recommend
|
||||
using them.
|
||||
|
||||
One of the reasons why is because a generated partial will call the original
|
||||
constructor of the mocked class. This can have unwanted side-effects during
|
||||
testing application code.
|
||||
|
||||
See :doc:`../cookbook/not_calling_the_constructor` for more details.
|
||||
|
||||
Proxied partial test doubles
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A proxied partial mock is a partial of last resort. We may encounter a class
|
||||
which is simply not capable of being mocked because it has been marked as
|
||||
final. Similarly, we may find a class with methods marked as final. In such a
|
||||
scenario, we cannot simply extend the class and override methods to mock - we
|
||||
need to get creative.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock(new MyClass);
|
||||
|
||||
Yes, the new mock is a Proxy. It intercepts calls and reroutes them to the
|
||||
proxied object (which we construct and pass in) for methods which are not
|
||||
subject to any expectations. Indirectly, this allows us to mock methods
|
||||
marked final since the Proxy is not subject to those limitations. The tradeoff
|
||||
should be obvious - a proxied partial will fail any typehint checks for the
|
||||
class being mocked since it cannot extend that class.
|
||||
|
||||
.. _creating-test-doubles-aliasing:
|
||||
|
||||
Aliasing
|
||||
--------
|
||||
|
||||
Prefixing the valid name of a class (which is NOT currently loaded) with
|
||||
"alias:" will generate an "alias mock". Alias mocks create a class alias with
|
||||
the given classname to stdClass and are generally used to enable the mocking
|
||||
of public static methods. Expectations set on the new mock object which refer
|
||||
to static methods will be used by all static calls to this class.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('alias:MyClass');
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Even though aliasing classes is supported, we do not recommend it.
|
||||
|
||||
Overloading
|
||||
-----------
|
||||
|
||||
Prefixing the valid name of a class (which is NOT currently loaded) with
|
||||
"overload:" will generate an alias mock (as with "alias:") except that created
|
||||
new instances of that class will import any expectations set on the origin
|
||||
mock (``$mock``). The origin mock is never verified since it's used an
|
||||
expectation store for new instances. For this purpose we use the term "instance
|
||||
mock" to differentiate it from the simpler "alias mock".
|
||||
|
||||
In other words, an instance mock will "intercept" when a new instance of the
|
||||
mocked class is created, then the mock will be used instead. This is useful
|
||||
especially when mocking hard dependencies which will be discussed later.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('overload:MyClass');
|
||||
|
||||
.. note::
|
||||
|
||||
Using alias/instance mocks across more than one test will generate a fatal
|
||||
error since we can't have two classes of the same name. To avoid this,
|
||||
run each test of this kind in a separate PHP process (which is supported
|
||||
out of the box by both PHPUnit and PHPT).
|
||||
|
||||
|
||||
.. _creating-test-doubles-named-mocks:
|
||||
|
||||
Named Mocks
|
||||
-----------
|
||||
|
||||
The ``namedMock()`` method will generate a class called by the first argument,
|
||||
so in this example ``MyClassName``. The rest of the arguments are treated in the
|
||||
same way as the ``mock`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::namedMock('MyClassName', 'DateTime');
|
||||
|
||||
This example would create a class called ``MyClassName`` that extends
|
||||
``DateTime``.
|
||||
|
||||
Named mocks are quite an edge case, but they can be useful when code depends
|
||||
on the ``__CLASS__`` magic constant, or when we need two derivatives of an
|
||||
abstract type, that are actually different classes.
|
||||
|
||||
See the cookbook entry on :doc:`../cookbook/class_constants` for an example
|
||||
usage of named mocks.
|
||||
|
||||
.. note::
|
||||
|
||||
We can only create a named mock once, any subsequent calls to
|
||||
``namedMock``, with different arguments are likely to cause exceptions.
|
||||
|
||||
.. _creating-test-doubles-constructor-arguments:
|
||||
|
||||
Constructor Arguments
|
||||
---------------------
|
||||
|
||||
Sometimes the mocked class has required constructor arguments. We can pass these
|
||||
to Mockery as an indexed array, as the 2nd argument:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass', [$constructorArg1, $constructorArg2]);
|
||||
|
||||
or if we need the ``MyClass`` to implement an interface as well, as the 3rd
|
||||
argument:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass', 'MyInterface', [$constructorArg1, $constructorArg2]);
|
||||
|
||||
Mockery now knows to pass in ``$constructorArg1`` and ``$constructorArg2`` as
|
||||
arguments to the constructor.
|
||||
|
||||
.. _creating-test-doubles-behavior-modifiers:
|
||||
|
||||
Behavior Modifiers
|
||||
------------------
|
||||
|
||||
When creating a mock object, we may wish to use some commonly preferred
|
||||
behaviours that are not the default in Mockery.
|
||||
|
||||
The use of the ``shouldIgnoreMissing()`` behaviour modifier will label this
|
||||
mock object as a Passive Mock:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::mock('MyClass')->shouldIgnoreMissing();
|
||||
|
||||
In such a mock object, calls to methods which are not covered by expectations
|
||||
will return ``null`` instead of the usual error about there being no expectation
|
||||
matching the call.
|
||||
|
||||
On PHP >= 7.0.0, methods with missing expectations that have a return type
|
||||
will return either a mock of the object (if return type is a class) or a
|
||||
"falsy" primitive value, e.g. empty string, empty array, zero for ints and
|
||||
floats, false for bools, or empty closures.
|
||||
|
||||
On PHP >= 7.1.0, methods with missing expectations and nullable return type
|
||||
will return null.
|
||||
|
||||
We can optionally prefer to return an object of type ``\Mockery\Undefined``
|
||||
(i.e. a ``null`` object) (which was the 0.7.2 behaviour) by using an
|
||||
additional modifier:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\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
|
||||
logic check.
|
||||
|
||||
We have encountered the ``makePartial()`` method before, as it is the method we
|
||||
use to create runtime partial test doubles:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::mock('MyClass')->makePartial();
|
||||
|
||||
This form of mock object will defer all methods not subject to an expectation to
|
||||
the parent class of the mock, i.e. ``MyClass``. Whereas the previous
|
||||
``shouldIgnoreMissing()`` returned ``null``, this behaviour simply calls the
|
||||
parent's matching method.
|
||||
@@ -12,13 +12,13 @@ similar to:
|
||||
$object->foo()->bar()->zebra()->alpha()->selfDestruct();
|
||||
|
||||
The long chain of method calls isn't necessarily a bad thing, assuming they
|
||||
each link back to a local object the calling class knows. Just as a fun
|
||||
example, Mockery's long chains (after the first ``shouldReceive()`` method)
|
||||
all call to the same instance of ``\Mockery\Expectation``. However, sometimes
|
||||
this is not the case and the chain is constantly crossing object boundaries.
|
||||
each link back to a local object the calling class knows. As a fun example,
|
||||
Mockery's long chains (after the first ``shouldReceive()`` method) all call to
|
||||
the same instance of ``\Mockery\Expectation``. However, sometimes this is not
|
||||
the case and the chain is constantly crossing object boundaries.
|
||||
|
||||
In either case, mocking such a chain can be a horrible task. To make it easier
|
||||
Mockery support demeter chain mocking. Essentially, we shortcut through the
|
||||
Mockery supports demeter chain mocking. Essentially, we shortcut through the
|
||||
chain and return a defined value from the final call. For example, let's
|
||||
assume ``selfDestruct()`` returns the string "Ten!" to $object (an instance of
|
||||
``CaptainsConsole``). Here's how we could mock it.
|
||||
|
||||
@@ -4,256 +4,529 @@
|
||||
Expectation Declarations
|
||||
========================
|
||||
|
||||
Once you have created a mock object, you'll often want to start defining how
|
||||
.. note::
|
||||
|
||||
In order for our expectations to work we MUST call ``Mockery::close()``,
|
||||
preferably in a callback method such as ``tearDown`` or ``_after``
|
||||
(depending on whether or not we're integrating Mockery with another
|
||||
framework). This static call cleans up the Mockery container used by the
|
||||
current test, and run any verification tasks needed for our expectations.
|
||||
|
||||
Once we have created a mock object, we'll often want to start defining how
|
||||
exactly it should behave (and how it should be called). This is where the
|
||||
Mockery expectation declarations take over.
|
||||
|
||||
.. code-block:: php
|
||||
Declaring Method Call Expectations
|
||||
----------------------------------
|
||||
|
||||
shouldReceive(method_name)
|
||||
|
||||
Declares that the mock expects a call to the given method name. This is the
|
||||
starting expectation upon which all other expectations and constraints are
|
||||
appended.
|
||||
To tell our test double to expect a call for a method with a given name, we use
|
||||
the ``shouldReceive`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
shouldReceive(method1, method2, ...)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method');
|
||||
|
||||
Declares a number of expected method calls, all of which will adopt any
|
||||
chained expectations or constraints.
|
||||
This is the starting expectation upon which all other expectations and
|
||||
constraints are appended.
|
||||
|
||||
We can declare more than one method call to be expected:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
shouldReceive(array('method1'=>1, 'method2'=>2, ...))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method_1', 'name_of_method_2');
|
||||
|
||||
Declares a number of expected calls but also their return values. All will
|
||||
adopt any additional chained expectations or constraints.
|
||||
All of these will adopt any chained expectations or constraints.
|
||||
|
||||
It is possible to declare the expectations for the method calls, along with
|
||||
their return values:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
shouldReceive(closure)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive([
|
||||
'name_of_method_1' => 'return value 1',
|
||||
'name_of_method_2' => 'return value 2',
|
||||
]);
|
||||
|
||||
Creates a mock object (only from a partial mock) which is used to create a
|
||||
mock object recorder. The recorder is a simple proxy to the original object
|
||||
passed in for mocking. This is passed to the closure, which may run it through
|
||||
a set of operations which are recorded as expectations on the partial mock. A
|
||||
simple use case is automatically recording expectations based on an existing
|
||||
usage (e.g. during refactoring). See examples in a later section.
|
||||
There's also a shorthand way of setting up method call expectations and their
|
||||
return values:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
shouldNotReceive(method_name)
|
||||
$mock = \Mockery::mock('MyClass', ['name_of_method_1' => 'return value 1', 'name_of_method_2' => 'return value 2']);
|
||||
|
||||
Declares that the mock should not expect a call to the given method name. This
|
||||
method is a convenience method for calling ``shouldReceive()->never()``.
|
||||
All of these will adopt any additional chained expectations or constraints.
|
||||
|
||||
We can declare that a test double should not expect a call to the given method
|
||||
name:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
with(arg1, arg2, ...) / withArgs(array(arg1, arg2, ...))
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldNotReceive('name_of_method');
|
||||
|
||||
Adds a constraint that this expectation only applies to method calls which
|
||||
match the expected argument list. You can add a lot more flexibility to
|
||||
argument matching using the built in matcher classes (see later). For example,
|
||||
``\Mockery::any()`` matches any argument passed to that position in the
|
||||
``with()`` parameter list. Mockery also allows Hamcrest library matchers - for
|
||||
example, the Hamcrest function ``anything()`` is equivalent to
|
||||
``\Mockery::any()``.
|
||||
This method is a convenience method for calling ``shouldReceive()->never()``.
|
||||
|
||||
Declaring Method Argument Expectations
|
||||
--------------------------------------
|
||||
|
||||
For every method we declare expectation for, we can add constraints that the
|
||||
defined expectations apply only to the method calls that match the expected
|
||||
argument list:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->with($arg1, $arg2, ...);
|
||||
// or
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->withArgs([$arg1, $arg2, ...]);
|
||||
|
||||
We can add a lot more flexibility to argument matching using the built in
|
||||
matcher classes (see later). For example, ``\Mockery::any()`` matches any
|
||||
argument passed to that position in the ``with()`` parameter list. Mockery also
|
||||
allows Hamcrest library matchers - for example, the Hamcrest function
|
||||
``anything()`` is equivalent to ``\Mockery::any()``.
|
||||
|
||||
It's important to note that this means all expectations attached only apply to
|
||||
the given method when it is called with these exact arguments. This allows for
|
||||
setting up differing expectations based on the arguments provided to expected
|
||||
calls.
|
||||
the given method when it is called with these exact arguments:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
withAnyArgs()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
|
||||
Declares that this expectation matches a method call regardless of what
|
||||
arguments are passed. This is set by default unless otherwise specified.
|
||||
$mock->shouldReceive('foo')->with('Hello');
|
||||
|
||||
$mock->foo('Goodbye'); // throws a NoMatchingExpectationException
|
||||
|
||||
This allows for setting up differing expectations based on the arguments
|
||||
provided to expected calls.
|
||||
|
||||
Argument matching with closures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Instead of providing a built-in matcher for each argument, we can provide a
|
||||
closure that matches all passed arguments at once:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
withNoArgs()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->withArgs(closure);
|
||||
|
||||
Declares this expectation matches method calls with zero arguments.
|
||||
The given closure receives all the arguments passed in the call to the expected
|
||||
method. In this way, this expectation only applies to method calls where passed
|
||||
arguments make the closure evaluate to true:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andReturn(value)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
|
||||
Sets a value to be returned from the expected method call.
|
||||
$mock->shouldReceive('foo')->withArgs(function ($arg) {
|
||||
if ($arg % 2 == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$mock->foo(4); // matches the expectation
|
||||
$mock->foo(3); // throws a NoMatchingExpectationException
|
||||
|
||||
Argument matching with some of given values
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
We can provide expected arguments that match passed arguments when mocked method
|
||||
is called.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andReturn(value1, value2, ...)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->withSomeOfArgs(arg1, arg2, arg3, ...);
|
||||
|
||||
Sets up a sequence of return values or closures. For example, the first call
|
||||
will return value1 and the second value2. Note that all subsequent calls to a
|
||||
mocked method will always return the final value (or the only value) given to
|
||||
this declaration.
|
||||
The given expected arguments order doesn't matter.
|
||||
Check if expected values are included or not, but type should be matched:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andReturnNull() / andReturn([NULL])
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('foo')
|
||||
->withSomeOfArgs(1, 2);
|
||||
|
||||
$mock->foo(1, 2, 3); // matches the expectation
|
||||
$mock->foo(3, 2, 1); // matches the expectation (passed order doesn't matter)
|
||||
$mock->foo('1', '2'); // throws a NoMatchingExpectationException (type should be matched)
|
||||
$mock->foo(3); // throws a NoMatchingExpectationException
|
||||
|
||||
Any, or no arguments
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
We can declare that the expectation matches a method call regardless of what
|
||||
arguments are passed:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->withAnyArgs();
|
||||
|
||||
This is set by default unless otherwise specified.
|
||||
|
||||
We can declare that the expectation matches method calls with zero arguments:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->withNoArgs();
|
||||
|
||||
Declaring Return Value Expectations
|
||||
-----------------------------------
|
||||
|
||||
For mock objects, we can tell Mockery what return values to return from the
|
||||
expected method calls.
|
||||
|
||||
For that we can use the ``andReturn()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturn($value);
|
||||
|
||||
This sets a value to be returned from the expected method call.
|
||||
|
||||
It is possible to set up expectation for multiple return values. By providing
|
||||
a sequence of return values, we tell Mockery what value to return on every
|
||||
subsequent call to the method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturn($value1, $value2, ...)
|
||||
|
||||
The first call will return ``$value1`` and the second call will return ``$value2``.
|
||||
|
||||
If we call the method more times than the number of return values we declared,
|
||||
Mockery will return the final value for any subsequent method call:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
|
||||
$mock->shouldReceive('foo')->andReturn(1, 2, 3);
|
||||
|
||||
$mock->foo(); // int(1)
|
||||
$mock->foo(); // int(2)
|
||||
$mock->foo(); // int(3)
|
||||
$mock->foo(); // int(3)
|
||||
|
||||
The same can be achieved using the alternative syntax:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturnValues([$value1, $value2, ...])
|
||||
|
||||
It accepts a simple array instead of a list of parameters. The order of return
|
||||
is determined by the numerical index of the given array with the last array
|
||||
member being returned on all calls once previous return values are exhausted.
|
||||
|
||||
The following two options are primarily for communication with test readers:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturnNull();
|
||||
// or
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturn([null]);
|
||||
|
||||
Both of the above options are primarily for communication to test readers.
|
||||
They mark the mock object method call as returning ``null`` or nothing.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andReturnValues(array)
|
||||
|
||||
Alternative syntax for ``andReturn()`` that accepts a simple array instead of
|
||||
a list of parameters. The order of return is determined by the numerical
|
||||
index of the given array with the last array member being return on all calls
|
||||
once previous return values are exhausted.
|
||||
Sometimes we want to calculate the return results of the method calls, based on
|
||||
the arguments passed to the method. We can do that with the ``andReturnUsing()``
|
||||
method which accepts one or more closure:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andReturnUsing(closure, ...)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturnUsing(closure, ...);
|
||||
|
||||
Sets a closure (anonymous function) to be called with the arguments passed to
|
||||
the method. The return value from the closure is then returned. Useful for
|
||||
some dynamic processing of arguments into related concrete results. Closures
|
||||
can queued by passing them as extra parameters as for ``andReturn()``.
|
||||
Closures can be queued by passing them as extra parameters as for ``andReturn()``.
|
||||
|
||||
Occasionally, it can be useful to echo back one of the arguments that a method
|
||||
is called with. In this case we can use the ``andReturnArg()`` method; the
|
||||
argument to be returned is specified by its index in the arguments list:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturnArg(1);
|
||||
|
||||
This returns the second argument (index #1) from the list of arguments when the
|
||||
method is called.
|
||||
|
||||
.. note::
|
||||
|
||||
You cannot currently mix ``andReturnUsing()`` with ``andReturn()``.
|
||||
We cannot currently mix ``andReturnUsing()`` or ``andReturnArg`` with
|
||||
``andReturn()``.
|
||||
|
||||
If we are mocking fluid interfaces, the following method will be helpful:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andThrow(Exception)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andReturnSelf();
|
||||
|
||||
Declares that this method will throw the given ``Exception`` object when
|
||||
called.
|
||||
It sets the return value to the mocked class name.
|
||||
|
||||
Throwing Exceptions
|
||||
-------------------
|
||||
|
||||
We can tell the method of mock objects to throw exceptions:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andThrow(exception_name, message)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andThrow(new Exception);
|
||||
|
||||
Rather than an object, you can pass in the ``Exception`` class and message to
|
||||
use when throwing an ``Exception`` from the mocked method.
|
||||
It will throw the given ``Exception`` object when called.
|
||||
|
||||
Rather than an object, we can pass in the ``Exception`` class, message and/or code to
|
||||
use when throwing an ``Exception`` from the mocked method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
andSet(name, value1) / set(name, value1)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andThrow('exception_name', 'message', 123456789);
|
||||
|
||||
Used with an expectation so that when a matching method is called, one can
|
||||
also cause a mock object's public property to be set to a specified value.
|
||||
.. _expectations-setting-public-properties:
|
||||
|
||||
Setting Public Properties
|
||||
-------------------------
|
||||
|
||||
Used with an expectation so that when a matching method is called, we can cause
|
||||
a mock object's public property to be set to a specified value, by using
|
||||
``andSet()`` or ``set()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->andSet($property, $value);
|
||||
// or
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->set($property, $value);
|
||||
|
||||
In cases where we want to call the real method of the class that was mocked and
|
||||
return its result, the ``passthru()`` method tells the expectation to bypass
|
||||
a return queue:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
passthru()
|
||||
|
||||
Tells the expectation to bypass a return queue and instead call the real
|
||||
method of the class that was mocked and return the result. Basically, it
|
||||
allows expectation matching and call count validation to be applied against
|
||||
It allows expectation matching and call count validation to be applied against
|
||||
real methods while still calling the real class method with the expected
|
||||
arguments.
|
||||
|
||||
.. code-block:: php
|
||||
Declaring Call Count Expectations
|
||||
---------------------------------
|
||||
|
||||
zeroOrMoreTimes()
|
||||
Besides setting expectations on the arguments of the method calls, and the
|
||||
return values of those same calls, we can set expectations on how many times
|
||||
should any method be called.
|
||||
|
||||
Declares that the expected method may be called zero or more times. This is
|
||||
the default for all methods unless otherwise set.
|
||||
When a call count expectation is not met, a
|
||||
``\Mockery\Expectation\InvalidCountException`` will be thrown.
|
||||
|
||||
.. note::
|
||||
|
||||
It is absolutely required to call ``\Mockery::close()`` at the end of our
|
||||
tests, for example in the ``tearDown()`` method of PHPUnit. Otherwise
|
||||
Mockery will not verify the calls made against our mock objects.
|
||||
|
||||
We can declare that the expected method may be called zero or more times:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
once()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->zeroOrMoreTimes();
|
||||
|
||||
Declares that the expected method may only be called once. Like all other call
|
||||
count constraints, it will throw a ``\Mockery\CountValidator\Exception`` if
|
||||
breached and can be modified by the ``atLeast()`` and ``atMost()``
|
||||
constraints.
|
||||
This is the default for all methods unless otherwise set.
|
||||
|
||||
To tell Mockery to expect an exact number of calls to a method, we can use the
|
||||
following:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
twice()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->times($n);
|
||||
|
||||
Declares that the expected method may only be called twice.
|
||||
where ``$n`` is the number of times the method should be called.
|
||||
|
||||
A couple of most common cases got their shorthand methods.
|
||||
|
||||
To declare that the expected method must be called one time only:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
times(n)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->once();
|
||||
|
||||
Declares that the expected method may only be called n times.
|
||||
To declare that the expected method must be called two times:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
never()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->twice();
|
||||
|
||||
Declares that the expected method may never be called. Ever!
|
||||
To declare that the expected method must never be called:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
atLeast()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->never();
|
||||
|
||||
Call count modifiers
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The call count expectations can have modifiers set.
|
||||
|
||||
If we want to tell Mockery the minimum number of times a method should be called,
|
||||
we use ``atLeast()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->atLeast()
|
||||
->times(3);
|
||||
|
||||
Adds a minimum modifier to the next call count expectation. Thus
|
||||
``atLeast()->times(3)`` means the call must be called at least three times
|
||||
(given matching method args) but never less than three times.
|
||||
|
||||
Similarly, we can tell Mockery the maximum number of times a method should be
|
||||
called, using ``atMost()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
atMost()
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->atMost()
|
||||
->times(3);
|
||||
|
||||
Adds a maximum modifier to the next call count expectation. Thus
|
||||
``atMost()->times(3)`` means the call must be called no more than three times.
|
||||
This also means no calls are acceptable.
|
||||
If the method gets no calls at all, the expectation will still be met.
|
||||
|
||||
We can also set a range of call counts, using ``between()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
between(min, max)
|
||||
$mock = \Mockery::mock('MyClass');
|
||||
$mock->shouldReceive('name_of_method')
|
||||
->between($min, $max);
|
||||
|
||||
Sets an expected range of call counts. This is actually identical to using
|
||||
``atLeast()->times(min)->atMost()->times(max)`` but is provided as a
|
||||
shorthand. It may be followed by a ``times()`` call with no parameter to
|
||||
preserve the APIs natural language readability.
|
||||
This is actually identical to using ``atLeast()->times($min)->atMost()->times($max)``
|
||||
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
|
||||
---------------------------------
|
||||
|
||||
Declares that this method is expected to be called in a specific order in
|
||||
relation to similarly marked methods.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
ordered()
|
||||
|
||||
Declares that this method is expected to be called in a specific order in
|
||||
relation to similarly marked methods. The order is dictated by the order in
|
||||
which this modifier is actually used when setting up mocks.
|
||||
The order is dictated by the order in which this modifier is actually used when
|
||||
setting up mocks.
|
||||
|
||||
Declares the method as belonging to an order group (which can be named or
|
||||
numbered). Methods within a group can be called in any order, but the ordered
|
||||
calls from outside the group are ordered in relation to the group:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
ordered(group)
|
||||
|
||||
Declares the method as belonging to an order group (which can be named or
|
||||
numbered). Methods within a group can be called in any order, but the ordered
|
||||
calls from outside the group are ordered in relation to the group, i.e. you
|
||||
can set up so that method1 is called before group1 which is in turn called
|
||||
before method 2.
|
||||
We can set up so that method1 is called before group1 which is in turn called
|
||||
before method2.
|
||||
|
||||
When called prior to ``ordered()`` or ``ordered(group)``, it declares this
|
||||
ordering to apply across all mock objects (not just the current mock):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
globally()
|
||||
|
||||
When called prior to ``ordered()`` or ``ordered(group)``, it declares this
|
||||
ordering to apply across all mock objects (not just the current mock). This
|
||||
allows for dictating order expectations across multiple mocks.
|
||||
This allows for dictating order expectations across multiple mocks.
|
||||
|
||||
The ``byDefault()`` marks an expectation as a default. Default expectations are
|
||||
applied unless a non-default expectation is created:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
byDefault()
|
||||
|
||||
Marks an expectation as a default. Default expectations are applied unless a
|
||||
non-default expectation is created. These later expectations immediately
|
||||
replace the previously defined default. This is useful so you can setup
|
||||
default mocks in your unit test ``setup()`` and later tweak them in specific
|
||||
tests as needed.
|
||||
These later expectations immediately replace the previously defined default.
|
||||
This is useful so we can setup default mocks in our unit test ``setup()`` and
|
||||
later tweak them in specific tests as needed.
|
||||
|
||||
Returns the current mock object from an expectation chain:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
getMock()
|
||||
|
||||
Returns the current mock object from an expectation chain. Useful where you
|
||||
prefer to keep mock setups as a single statement, e.g.
|
||||
Useful where we prefer to keep mock setups as a single statement, e.g.:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
|
||||
@@ -7,17 +7,23 @@ Dealing with Final Classes/Methods
|
||||
One of the primary restrictions of mock objects in PHP, is that mocking
|
||||
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.
|
||||
inherit the type of the class or object being mocked).
|
||||
|
||||
The simplest solution is not to 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
|
||||
being mocked, i.e. it will not pass any instanceof comparison.
|
||||
being mocked, i.e. it will not pass any instanceof comparison. Methods marked
|
||||
as final will be proxied to the original method, i.e., final methods can't be
|
||||
mocked.
|
||||
|
||||
You can create a proxy mock by passing the instantiated object you wish to
|
||||
We can create a proxy mock by passing the instantiated object we wish to
|
||||
mock into ``\Mockery::mock()``, i.e. Mockery will then generate a Proxy to the
|
||||
real object and selectively intercept method calls for the purposes of setting
|
||||
and meeting expectations.
|
||||
|
||||
See the :ref:`creating-test-doubles-partial-test-doubles` chapter, the subsection
|
||||
about proxied partial test doubles.
|
||||
|
||||
@@ -4,17 +4,19 @@ Reference
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
startup_methods
|
||||
creating_test_doubles
|
||||
expectations
|
||||
argument_validation
|
||||
alternative_should_receive_syntax
|
||||
spies
|
||||
partial_mocks
|
||||
protected_methods
|
||||
public_properties
|
||||
public_static_properties
|
||||
pass_by_reference_behaviours
|
||||
demeter_chains
|
||||
object_recording
|
||||
final_methods_classes
|
||||
magic_methods
|
||||
mockery/index
|
||||
phpunit_integration
|
||||
|
||||
.. include:: map.rst.inc
|
||||
|
||||
@@ -10,7 +10,7 @@ It is strongly recommended that unit tests and mock objects do not directly
|
||||
refer to magic methods. Instead, refer only to the virtual methods and
|
||||
properties these magic methods simulate.
|
||||
|
||||
Following this piece of advice will ensure you are testing the real API of
|
||||
Following this piece of advice will ensure we are testing the real API of
|
||||
classes and also ensures there is no conflict should Mockery override these
|
||||
magic methods, which it will inevitably do in order to support its role in
|
||||
intercepting method calls and properties.
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
* :doc:`/reference/startup_methods`
|
||||
* :doc:`/reference/creating_test_doubles`
|
||||
* :doc:`/reference/expectations`
|
||||
* :doc:`/reference/argument_validation`
|
||||
* :doc:`/reference/alternative_should_receive_syntax`
|
||||
* :doc:`/reference/spies`
|
||||
* :doc:`/reference/partial_mocks`
|
||||
* :doc:`/reference/protected_methods`
|
||||
* :doc:`/reference/public_properties`
|
||||
* :doc:`/reference/public_static_properties`
|
||||
* :doc:`/reference/pass_by_reference_behaviours`
|
||||
* :doc:`/reference/demeter_chains`
|
||||
* :doc:`/reference/object_recording`
|
||||
* :doc:`/reference/final_methods_classes`
|
||||
* :doc:`/reference/magic_methods`
|
||||
|
||||
Mockery Reference
|
||||
-----------------
|
||||
|
||||
* :doc:`/reference/mockery/configuration`
|
||||
* :doc:`/reference/mockery/exceptions`
|
||||
* :doc:`/reference/mockery/reserved_method_names`
|
||||
* :doc:`/reference/mockery/gotchas`
|
||||
* :doc:`/reference/phpunit_integration`
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
.. index::
|
||||
single: Mockery; Configuration
|
||||
|
||||
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 three
|
||||
currently present include:
|
||||
|
||||
* Option to allow/disallow the mocking of methods which do not actually exist
|
||||
* Option to allow/disallow the existence of expectations which are never
|
||||
fulfilled (i.e. unused)
|
||||
* Setter/Getter for added a parameter map for internal PHP class methods
|
||||
(``Reflection`` cannot detect these automatically)
|
||||
|
||||
By default, the first two behaviours are enabled. Of course, there are
|
||||
situations where this can lead to unintended consequences. The mocking of
|
||||
non-existent methods may allow mocks based on real classes/objects to fall out
|
||||
of sync with the actual implementations, especially when some degree of
|
||||
integration testing (testing of object wiring) is not being performed.
|
||||
Allowing unfulfilled expectations means unnecessary mock expectations go
|
||||
unnoticed, cluttering up test code, and potentially confusing test readers.
|
||||
|
||||
You may allow or disallow these behaviours (whether for whole test suites or
|
||||
just select tests) by using one or both of the following two calls:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->allowMockingNonExistentMethods(bool);
|
||||
\Mockery::getConfiguration()->allowMockingMethodsUnnecessarily(bool);
|
||||
|
||||
Passing a true allows the behaviour, false disallows it. Both take effect
|
||||
immediately until switched back. In both cases, if either behaviour is
|
||||
detected when not allowed, it will result in an Exception being thrown at that
|
||||
point. Note that disallowing these behaviours should be carefully considered
|
||||
since they necessarily remove at least some of Mockery's flexibility.
|
||||
|
||||
The other two methods are:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::getConfiguration()->setInternalClassMethodParamMap($class, $method, array $paramMap)
|
||||
\Mockery::getConfiguration()->getInternalClassMethodParamMap($class, $method)
|
||||
|
||||
These are used to define parameters (i.e. the signature string of each) for the
|
||||
methods of internal PHP classes (e.g. SPL, or PECL extension classes like
|
||||
ext/mongo's MongoCollection. Reflection cannot analyse the parameters of internal
|
||||
classes. Most of the time, you never need to do this. It's mainly needed where an
|
||||
internal class method uses pass-by-reference for a parameter - you MUST in such
|
||||
cases ensure the parameter signature includes the ``&`` symbol correctly as Mockery
|
||||
won't correctly add it automatically for internal classes.
|
||||
@@ -1,93 +0,0 @@
|
||||
.. index::
|
||||
single: Mocking; Object Recording
|
||||
|
||||
Mock Object Recording
|
||||
=====================
|
||||
|
||||
In certain cases, you may find that you are testing against an already
|
||||
established pattern of behaviour, perhaps during refactoring. Rather then hand
|
||||
crafting mock object expectations for this behaviour, you could instead use
|
||||
the existing source code to record the interactions a real object undergoes
|
||||
onto a mock object as expectations - expectations you can then verify against
|
||||
an alternative or refactored version of the source code.
|
||||
|
||||
To record expectations, you need a concrete instance of the class to be
|
||||
mocked. This can then be used to create a partial mock to which is given the
|
||||
necessary code to execute the object interactions to be recorded. A simple
|
||||
example is outline below (we use a closure for passing instructions to the
|
||||
mock).
|
||||
|
||||
Here we have a very simple setup, a class (``SubjectUser``) which uses another
|
||||
class (``Subject``) to retrieve some value. We want to record as expectations
|
||||
on our mock (which will replace ``Subject`` later) all the calls and return
|
||||
values of a Subject instance when interacting with ``SubjectUser``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Subject
|
||||
{
|
||||
|
||||
public function execute() {
|
||||
return 'executed!';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SubjectUser
|
||||
{
|
||||
|
||||
public function use(Subject $subject) {
|
||||
return $subject->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Here's the test case showing the recording:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class SubjectUserTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
\Mockery::close();
|
||||
}
|
||||
|
||||
public function testSomething()
|
||||
{
|
||||
$mock = \Mockery::mock(new Subject);
|
||||
$mock->shouldExpect(function ($subject) {
|
||||
$user = new SubjectUser;
|
||||
$user->use($subject);
|
||||
});
|
||||
|
||||
/**
|
||||
* Assume we have a replacement SubjectUser called NewSubjectUser.
|
||||
* We want to verify it behaves identically to SubjectUser, i.e.
|
||||
* it uses Subject in the exact same way
|
||||
*/
|
||||
$newSubject = new NewSubjectUser;
|
||||
$newSubject->use($mock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
After the ``\Mockery::close()`` call in ``tearDown()`` validates the mock
|
||||
object, we should have zero exceptions if ``NewSubjectUser`` acted on
|
||||
`Subject` in a similar way to ``SubjectUser``. By default the order of calls
|
||||
are not enforced, and loose argument matching is enabled, i.e. arguments may
|
||||
be equal (``==``) but not necessarily identical (``===``).
|
||||
|
||||
If you wished to be more strict, for example ensuring the order of calls and
|
||||
the final call counts were identical, or ensuring arguments are completely
|
||||
identical, you can invoke the recorder's strict mode from the closure block,
|
||||
e.g.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock->shouldExpect(function ($subject) {
|
||||
$subject->shouldBeStrict();
|
||||
$user = new SubjectUser;
|
||||
$user->use($subject);
|
||||
});
|
||||
@@ -4,64 +4,78 @@
|
||||
Creating Partial Mocks
|
||||
======================
|
||||
|
||||
Partial mocks are useful when you only need to mock several methods of an
|
||||
Partial mocks are useful when we only need to mock several methods of an
|
||||
object leaving the remainder free to respond to calls normally (i.e. as
|
||||
implemented). Mockery implements three distinct strategies for creating
|
||||
partials. Each has specific advantages and disadvantages so which strategy you
|
||||
use will depend on your own preferences and the source code in need of
|
||||
partials. Each has specific advantages and disadvantages so which strategy we
|
||||
use will depend on our own preferences and the source code in need of
|
||||
mocking.
|
||||
|
||||
#. Traditional Partial Mock
|
||||
#. Passive Partial Mock
|
||||
We have previously talked a bit about :ref:`creating-test-doubles-partial-test-doubles`,
|
||||
but we'd like to expand on the subject a bit here.
|
||||
|
||||
#. Runtime partial test doubles
|
||||
#. Generated partial test doubles
|
||||
#. Proxied Partial Mock
|
||||
|
||||
Traditional Partial Mock
|
||||
------------------------
|
||||
Runtime partial test doubles
|
||||
----------------------------
|
||||
|
||||
A traditional partial mock, defines ahead of time which methods of a class are
|
||||
to be mocked and which are to be left unmocked (i.e. callable as normal). The
|
||||
syntax for creating traditional mocks is:
|
||||
A runtime partial test double, also known as a passive partial mock, is a kind
|
||||
of a default state of being for a mocked object.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass')->makePartial();
|
||||
|
||||
With a runtime partial, we assume that all methods will simply defer to the
|
||||
parent class (``MyClass``) original methods unless a method call matches a
|
||||
known expectation. If we have no matching expectation for a specific method
|
||||
call, that call is deferred to the class being mocked. Since the division
|
||||
between mocked and unmocked calls depends entirely on the expectations we
|
||||
define, there is no need to define which methods to mock in advance.
|
||||
|
||||
See the cookbook entry on :doc:`../cookbook/big_parent_class` for an example
|
||||
usage of runtime partial test doubles.
|
||||
|
||||
Generated Partial Test Doubles
|
||||
------------------------------
|
||||
|
||||
A generated partial test double, also known as a traditional partial mock,
|
||||
defines ahead of time which methods of a class are to be mocked and which are
|
||||
to be left unmocked (i.e. callable as normal). The syntax for creating
|
||||
traditional mocks is:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass[foo,bar]');
|
||||
|
||||
In the above example, the ``foo()`` and ``bar()`` methods of MyClass will be
|
||||
mocked but no other MyClass methods are touched. You will need to define
|
||||
mocked but no other MyClass methods are touched. We will need to define
|
||||
expectations for the ``foo()`` and ``bar()`` methods to dictate their mocked
|
||||
behaviour.
|
||||
|
||||
Don't forget that you can pass in constructor arguments since unmocked methods
|
||||
Don't forget that we can pass in constructor arguments since unmocked methods
|
||||
may rely on those!
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyNamespace\MyClass[foo]', array($arg1, $arg2));
|
||||
|
||||
Passive Partial Mock
|
||||
--------------------
|
||||
See the :ref:`creating-test-doubles-constructor-arguments` section to read up
|
||||
on them.
|
||||
|
||||
A passive partial mock is more of a default state of being.
|
||||
.. note::
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyClass')->makePartial();
|
||||
|
||||
In a passive partial, we assume that all methods will simply defer to the
|
||||
parent class (``MyClass``) original methods unless a method call matches a
|
||||
known expectation. If you have no matching expectation for a specific method
|
||||
call, that call is deferred to the class being mocked. Since the division
|
||||
between mocked and unmocked calls depends entirely on the expectations you
|
||||
define, there is no need to define which methods to mock in advance. The
|
||||
``makePartial()`` method is identical to the original ``shouldDeferMissing()``
|
||||
method which first introduced this Partial Mock type.
|
||||
Even though we support generated partial test doubles, we do not recommend
|
||||
using them.
|
||||
|
||||
Proxied Partial Mock
|
||||
--------------------
|
||||
|
||||
A proxied partial mock is a partial of last resort. You may encounter a class
|
||||
A proxied partial mock is a partial of last resort. We may encounter a class
|
||||
which is simply not capable of being mocked because it has been marked as
|
||||
final. Similarly, you may find a class with methods marked as final. In such a
|
||||
final. Similarly, we may find a class with methods marked as final. In such a
|
||||
scenario, we cannot simply extend the class and override methods to mock - we
|
||||
need to get creative.
|
||||
|
||||
@@ -70,8 +84,8 @@ need to get creative.
|
||||
$mock = \Mockery::mock(new MyClass);
|
||||
|
||||
Yes, the new mock is a Proxy. It intercepts calls and reroutes them to the
|
||||
proxied object (which you construct and pass in) for methods which are not
|
||||
subject to any expectations. Indirectly, this allows you to mock methods
|
||||
proxied object (which we construct and pass in) for methods which are not
|
||||
subject to any expectations. Indirectly, this allows us to mock methods
|
||||
marked final since the Proxy is not subject to those limitations. The tradeoff
|
||||
should be obvious - a proxied partial will fail any typehint checks for the
|
||||
class being mocked since it cannot extend that class.
|
||||
@@ -79,15 +93,15 @@ class being mocked since it cannot extend that class.
|
||||
Special Internal Cases
|
||||
----------------------
|
||||
|
||||
All mock objects, with the exception of Proxied Partials, allow you to make
|
||||
any expectation call the underlying real class method using the ``passthru()``
|
||||
All mock objects, with the exception of Proxied Partials, allows us to make
|
||||
any expectation call to the underlying real class method using the ``passthru()``
|
||||
expectation call. This will return values from the real call and bypass any
|
||||
mocked return queue (which can simply be omitted obviously).
|
||||
|
||||
There is a fourth kind of partial mock reserved for internal use. This is
|
||||
automatically generated when you attempt to mock a class containing methods
|
||||
automatically generated when we attempt to mock a class containing methods
|
||||
marked final. Since we cannot override such methods, they are simply left
|
||||
unmocked. Typically, you don't need to worry about this but if you really
|
||||
unmocked. Typically, we don't need to worry about this but if we really
|
||||
really must mock a final method, the only possible means is through a Proxied
|
||||
Partial Mock. SplFileInfo, for example, is a common class subject to this form
|
||||
of automatic internal partial since it contains public final methods used
|
||||
|
||||
@@ -6,7 +6,7 @@ Preserving Pass-By-Reference Method Parameter Behaviour
|
||||
|
||||
PHP Class method may accept parameters by reference. In this case, changes
|
||||
made to the parameter (a reference to the original variable passed to the
|
||||
method) are reflected in the original variable. A simple example:
|
||||
method) are reflected in the original variable. An example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -26,21 +26,21 @@ method) are reflected in the original variable. A simple example:
|
||||
|
||||
echo $baz; // will echo the integer 2
|
||||
|
||||
In the example above, the variable $baz is passed by reference to
|
||||
In the example above, the variable ``$baz`` is passed by reference to
|
||||
``Foo::bar()`` (notice the ``&`` symbol in front of the parameter?). Any
|
||||
change ``bar()`` makes to the parameter reference is reflected in the original
|
||||
variable, ``$baz``.
|
||||
|
||||
Mockery 0.7+ handles references correctly for all methods where it can analyse
|
||||
Mockery handles references correctly for all methods where it can analyse
|
||||
the parameter (using ``Reflection``) to see if it is passed by reference. To
|
||||
mock how a reference is manipulated by the class method, you can use a closure
|
||||
mock how a reference is manipulated by the class method, we can use a closure
|
||||
argument matcher to manipulate it, i.e. ``\Mockery::on()`` - see the
|
||||
":doc:`argument_validation`" chapter.
|
||||
:ref:`argument-validation-complex-argument-validation` chapter.
|
||||
|
||||
There is an exception for internal PHP classes where Mockery cannot analyse
|
||||
method parameters using ``Reflection`` (a limitation in PHP). To work around
|
||||
this, you can explicitly declare method parameters for an internal class using
|
||||
``/Mockery/Configuration::setInternalClassMethodParamMap()``.
|
||||
this, we can explicitly declare method parameters for an internal class using
|
||||
``\Mockery\Configuration::setInternalClassMethodParamMap()``.
|
||||
|
||||
Here's an example using ``MongoCollection::insert()``. ``MongoCollection`` is
|
||||
an internal class offered by the mongo extension from PECL. Its ``insert()``
|
||||
@@ -81,3 +81,50 @@ preserved:
|
||||
|
||||
\Mockery::resetContainer();
|
||||
}
|
||||
|
||||
Protected Methods
|
||||
-----------------
|
||||
|
||||
When dealing with protected methods, and trying to preserve pass by reference
|
||||
behavior for them, a different approach is required.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Model
|
||||
{
|
||||
public function test(&$data)
|
||||
{
|
||||
return $this->doTest($data);
|
||||
}
|
||||
|
||||
protected function doTest(&$data)
|
||||
{
|
||||
$data['something'] = 'wrong';
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testModel()
|
||||
{
|
||||
$mock = \Mockery::mock('Model[test]')->shouldAllowMockingProtectedMethods();
|
||||
|
||||
$mock->shouldReceive('test')
|
||||
->with(\Mockery::on(function(&$data) {
|
||||
$data['something'] = 'wrong';
|
||||
return true;
|
||||
}));
|
||||
|
||||
$data = array('foo' => 'bar');
|
||||
|
||||
$mock->test($data);
|
||||
$this->assertTrue(isset($data['something']));
|
||||
$this->assertEquals('wrong', $data['something']);
|
||||
}
|
||||
}
|
||||
|
||||
This is quite an edge case, so we need to change the original code a little bit,
|
||||
by creating a public method that will call our protected method, and then mock
|
||||
that, instead of the protected method. This new public method will act as a
|
||||
proxy to our protected method.
|
||||
|
||||
@@ -6,8 +6,8 @@ PHPUnit Integration
|
||||
|
||||
Mockery was designed as a simple-to-use *standalone* mock object framework, so
|
||||
its need for integration with any testing framework is entirely optional. To
|
||||
integrate Mockery, you just need to define a ``tearDown()`` method for your
|
||||
tests containing the following (you may use a shorter ``\Mockery`` namespace
|
||||
integrate Mockery, we need to define a ``tearDown()`` method for our tests
|
||||
containing the following (we may use a shorter ``\Mockery`` namespace
|
||||
alias):
|
||||
|
||||
.. code-block:: php
|
||||
@@ -17,16 +17,16 @@ alias):
|
||||
}
|
||||
|
||||
This static call cleans up the Mockery container used by the current test, and
|
||||
run any verification tasks needed for your expectations.
|
||||
run any verification tasks needed for our expectations.
|
||||
|
||||
For some added brevity when it comes to using Mockery, you can also explicitly
|
||||
For some added brevity when it comes to using Mockery, we can also explicitly
|
||||
use the Mockery namespace with a shorter alias. For example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
|
||||
class SimpleTest extends PHPUnit_Framework_TestCase
|
||||
class SimpleTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testSimpleMock() {
|
||||
$mock = m::mock('simplemock');
|
||||
@@ -40,9 +40,9 @@ use the Mockery namespace with a shorter alias. For example:
|
||||
}
|
||||
}
|
||||
|
||||
Mockery ships with an autoloader so you don't need to litter your tests with
|
||||
``require_once()`` calls. To use it, ensure Mockery is on your
|
||||
``include_path`` and add the following to your test suite's ``Bootstrap.php``
|
||||
Mockery ships with an autoloader so we don't need to litter our tests with
|
||||
``require_once()`` calls. To use it, ensure Mockery is on our
|
||||
``include_path`` and add the following to our test suite's ``Bootstrap.php``
|
||||
or ``TestHelper.php`` file:
|
||||
|
||||
.. code-block:: php
|
||||
@@ -53,8 +53,8 @@ or ``TestHelper.php`` file:
|
||||
$loader = new \Mockery\Loader;
|
||||
$loader->register();
|
||||
|
||||
If you are using Composer, you can simplify this to just including the
|
||||
Composer generated autoloader file:
|
||||
If we are using Composer, we can simplify this to including the Composer
|
||||
generated autoloader file:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -67,22 +67,41 @@ Composer generated autoloader file:
|
||||
the file name is updated for all your projects.)
|
||||
|
||||
To integrate Mockery into PHPUnit and avoid having to call the close method
|
||||
and have Mockery remove itself from code coverage reports, use this in you
|
||||
suite:
|
||||
and have Mockery remove itself from code coverage reports, have your test case
|
||||
extends the ``\Mockery\Adapter\Phpunit\MockeryTestCase``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Create Suite
|
||||
$suite = new PHPUnit_Framework_TestSuite();
|
||||
class MyTest extends \Mockery\Adapter\Phpunit\MockeryTestCase
|
||||
{
|
||||
|
||||
// Create a result listener or add it
|
||||
$result = new PHPUnit_Framework_TestResult();
|
||||
$result->addListener(new \Mockery\Adapter\Phpunit\TestListener());
|
||||
}
|
||||
|
||||
// Run the tests.
|
||||
$suite->run($result);
|
||||
An alternative is to use the supplied trait:
|
||||
|
||||
If you are using PHPUnit's XML configuration approach, you can include the
|
||||
.. code-block:: php
|
||||
|
||||
class MyTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
||||
}
|
||||
|
||||
Extending ``MockeryTestCase`` or using the ``MockeryPHPUnitIntegration``
|
||||
trait is **the recommended way** of integrating Mockery with PHPUnit,
|
||||
since Mockery 1.0.0.
|
||||
|
||||
PHPUnit listener
|
||||
----------------
|
||||
|
||||
Before the 1.0.0 release, Mockery provided a PHPUnit listener that would
|
||||
call ``Mockery::close()`` for us at the end of a test. This has changed
|
||||
significantly since the 1.0.0 version.
|
||||
|
||||
Now, Mockery provides a PHPUnit listener that makes tests fail if
|
||||
``Mockery::close()`` has not been called. It can help identify tests where
|
||||
we've forgotten to include the trait or extend the ``MockeryTestCase``.
|
||||
|
||||
If we are using PHPUnit's XML configuration approach, we can include the
|
||||
following to load the ``TestListener``:
|
||||
|
||||
.. code-block:: xml
|
||||
@@ -92,19 +111,35 @@ following to load the ``TestListener``:
|
||||
</listeners>
|
||||
|
||||
Make sure Composer's or Mockery's autoloader is present in the bootstrap file
|
||||
or you will need to also define a "file" attribute pointing to the file of the
|
||||
above ``TestListener`` class.
|
||||
or we will need to also define a "file" attribute pointing to the file of the
|
||||
``TestListener`` class.
|
||||
|
||||
If we are creating the test suite programmatically we may add the listener
|
||||
like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Create the suite.
|
||||
$suite = new PHPUnit\Framework\TestSuite();
|
||||
|
||||
// Create the listener and add it to the suite.
|
||||
$result = new PHPUnit\Framework\TestResult();
|
||||
$result->addListener(new \Mockery\Adapter\Phpunit\TestListener());
|
||||
|
||||
// Run the tests.
|
||||
$suite->run($result);
|
||||
|
||||
.. caution::
|
||||
|
||||
PHPUnit provides a functionality that allows
|
||||
`tests to run in a separated process <http://phpunit.de/manual/4.0/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses>`_,
|
||||
`tests to run in a separated process <http://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses>`_,
|
||||
to ensure better isolation. Mockery verifies the mocks expectations using the
|
||||
``Mockery::close()`` method, and provides a PHPUnit listener, that automatically
|
||||
calls this method for you after every test.
|
||||
calls this method for us after every test.
|
||||
|
||||
However, this listener is not called in the right process when using PHPUnit's process
|
||||
isolation, resulting in expectations that might not be respected, but without raising
|
||||
any ``Mockery\Exception``. To avoid this, you cannot rely on the supplied Mockery PHPUnit
|
||||
``TestListener``, and you need to explicitly calls ``Mockery::close``. The easiest solution
|
||||
to include this call in the ``tearDown()`` method, as explained previously.
|
||||
However, this listener is not called in the right process when using
|
||||
PHPUnit's process isolation, resulting in expectations that might not be
|
||||
respected, but without raising any ``Mockery\Exception``. To avoid this,
|
||||
we cannot rely on the supplied Mockery PHPUnit ``TestListener``, and we need
|
||||
to explicitly call ``Mockery::close``. The easiest solution to include this
|
||||
call in the ``tearDown()`` method, as explained previously.
|
||||
|
||||
26
vendor/mockery/mockery/docs/reference/protected_methods.rst
vendored
Normal file
26
vendor/mockery/mockery/docs/reference/protected_methods.rst
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
.. index::
|
||||
single: Mocking; Protected Methods
|
||||
|
||||
Mocking Protected Methods
|
||||
=========================
|
||||
|
||||
By default, Mockery does not allow mocking protected methods. We do not recommend
|
||||
mocking protected methods, but there are cases when there is no other solution.
|
||||
|
||||
For those cases we have the ``shouldAllowMockingProtectedMethods()`` method. It
|
||||
instructs Mockery to specifically allow mocking of protected methods, for that
|
||||
one class only:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class MyClass
|
||||
{
|
||||
protected function foo()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
$mock = \Mockery::mock('MyClass')
|
||||
->shouldAllowMockingProtectedMethods();
|
||||
$mock->shouldReceive('foo');
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
Mocking Public Properties
|
||||
=========================
|
||||
|
||||
Mockery allows you to mock properties in several ways. The simplest is that
|
||||
you can simply set a public property and value on any mock object. The second
|
||||
is that you can use the expectation methods ``set()`` and ``andSet()`` to set
|
||||
property values if that expectation is ever met.
|
||||
Mockery allows us to mock properties in several ways. One way is that we can set
|
||||
a public property and its value on any mock object. The second is that we can
|
||||
use the expectation methods ``set()`` and ``andSet()`` to set property values if
|
||||
that expectation is ever met.
|
||||
|
||||
You should note that, in general, Mockery does not support mocking any magic
|
||||
methods since these are generally not considered a public API (and besides
|
||||
they are a PITA to differentiate when you badly need them for mocking!). So
|
||||
please mock virtual properties (those relying on ``__get()`` and ``__set()``)
|
||||
as if they were actually declared on the class.
|
||||
You can read more about :ref:`expectations-setting-public-properties`.
|
||||
|
||||
.. note::
|
||||
|
||||
In general, Mockery does not support mocking any magic methods since these
|
||||
are generally not considered a public API (and besides it is a bit difficult
|
||||
to differentiate them when you badly need them for mocking!). So please mock
|
||||
virtual properties (those relying on ``__get()`` and ``__set()``) as if they
|
||||
were actually declared on the class.
|
||||
|
||||
@@ -10,3 +10,6 @@ name which would normally be loaded (via autoloading or a require statement)
|
||||
in the system under test. These aliases block that loading (unless via a
|
||||
require statement - so please use autoloading!) and allow Mockery to intercept
|
||||
static method calls and add expectations for them.
|
||||
|
||||
See the :ref:`creating-test-doubles-aliasing` section for more information on
|
||||
creating aliased mocks, for the purpose of mocking public static methods.
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
.. index::
|
||||
single: Reference; Examples
|
||||
|
||||
Quick Examples
|
||||
==============
|
||||
|
||||
Create a mock object to return a sequence of values from a set of method
|
||||
calls.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class SimpleTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
\Mockery::close();
|
||||
}
|
||||
|
||||
public function testSimpleMock()
|
||||
{
|
||||
$mock = \Mockery::mock(array('pi' => 3.1416, 'e' => 2.71));
|
||||
$this->assertEquals(3.1416, $mock->pi());
|
||||
$this->assertEquals(2.71, $mock->e());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Create a mock object which returns a self-chaining Undefined object for a
|
||||
method call.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
|
||||
class UndefinedTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
public function testUndefinedValues()
|
||||
{
|
||||
$mock = m::mock('mymock');
|
||||
$mock->shouldReceive('divideBy')->with(0)->andReturnUndefined();
|
||||
$this->assertTrue($mock->divideBy(0) instanceof \Mockery\Undefined);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Creates a mock object which multiple query calls and a single update call.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
|
||||
class DbTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
public function testDbAdapter()
|
||||
{
|
||||
$mock = m::mock('db');
|
||||
$mock->shouldReceive('query')->andReturn(1, 2, 3);
|
||||
$mock->shouldReceive('update')->with(5)->andReturn(NULL)->once();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Expect all queries to be executed before any updates.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
|
||||
class DbTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
public function testQueryAndUpdateOrder()
|
||||
{
|
||||
$mock = m::mock('db');
|
||||
$mock->shouldReceive('query')->andReturn(1, 2, 3)->ordered();
|
||||
$mock->shouldReceive('update')->andReturn(NULL)->once()->ordered();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Create a mock object where all queries occur after startup, but before finish,
|
||||
and where queries are expected with several different params.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use \Mockery as m;
|
||||
|
||||
class DbTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
public function testOrderedQueries()
|
||||
{
|
||||
$db = m::mock('db');
|
||||
$db->shouldReceive('startup')->once()->ordered();
|
||||
$db->shouldReceive('query')->with('CPWR')->andReturn(12.3)->once()->ordered('queries');
|
||||
$db->shouldReceive('query')->with('MSFT')->andReturn(10.0)->once()->ordered('queries');
|
||||
$db->shouldReceive('query')->with("/^....$/")->andReturn(3.3)->atLeast()->once()->ordered('queries');
|
||||
$db->shouldReceive('finish')->once()->ordered();
|
||||
|
||||
// ... test code here using the mock
|
||||
}
|
||||
|
||||
}
|
||||
154
vendor/mockery/mockery/docs/reference/spies.rst
vendored
Normal file
154
vendor/mockery/mockery/docs/reference/spies.rst
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
.. index::
|
||||
single: Reference; Spies
|
||||
|
||||
Spies
|
||||
=====
|
||||
|
||||
Spies are a type of test doubles, but they differ from stubs or mocks in that,
|
||||
that the spies record any interaction between the spy and the System Under Test
|
||||
(SUT), and allow us to make assertions against those interactions after the fact.
|
||||
|
||||
Creating a spy means we don't have to set up expectations for every method call
|
||||
the double might receive during the test, some of which may not be relevant to
|
||||
the current test. A spy allows us to make assertions about the calls we care
|
||||
about for this test only, reducing the chances of over-specification and making
|
||||
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:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// arrange
|
||||
$mock = \Mockery::mock('MyDependency');
|
||||
$sut = new MyClass($mock);
|
||||
|
||||
// expect
|
||||
$mock->shouldReceive('foo')
|
||||
->once()
|
||||
->with('bar');
|
||||
|
||||
// act
|
||||
$sut->callFoo();
|
||||
|
||||
// assert
|
||||
\Mockery::close();
|
||||
|
||||
Spies allow us to skip the expect part and move the assertion to after we have
|
||||
acted on the SUT, usually making our tests more readable:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// arrange
|
||||
$spy = \Mockery::spy('MyDependency');
|
||||
$sut = new MyClass($spy);
|
||||
|
||||
// act
|
||||
$sut->callFoo();
|
||||
|
||||
// assert
|
||||
$spy->shouldHaveReceived()
|
||||
->foo()
|
||||
->with('bar');
|
||||
|
||||
On the other hand, spies are far less restrictive than mocks, meaning tests are
|
||||
usually less precise, as they let us get away with more. This is usually a
|
||||
good thing, they should only be as precise as they need to be, but while spies
|
||||
make our tests more intent-revealing, they do tend to reveal less about the
|
||||
design of the SUT. If we're having to setup lots of expectations for a mock,
|
||||
in lots of different tests, our tests are trying to tell us something - the SUT
|
||||
is doing too much and probably should be refactored. We don't get this with
|
||||
spies, they simply ignore the calls that aren't relevant to them.
|
||||
|
||||
Another downside to using spies is debugging. When a mock receives a call that
|
||||
it wasn't expecting, it immediately throws an exception (failing fast), giving
|
||||
us a nice stack trace or possibly even invoking our debugger. With spies, we're
|
||||
simply asserting calls were made after the fact, so if the wrong calls were made,
|
||||
we don't have quite the same just in time context we have with the mocks.
|
||||
|
||||
Finally, if we need to define a return value for our test double, we can't do
|
||||
that with a spy, only with a mock object.
|
||||
|
||||
.. note::
|
||||
|
||||
This documentation page is an adaption of the blog post titled
|
||||
`"Mockery Spies" <https://davedevelopment.co.uk/2014/10/09/mockery-spies.html>`_,
|
||||
published by Dave Marshall on his blog. Dave is the original author of spies
|
||||
in Mockery.
|
||||
|
||||
Spies Reference
|
||||
---------------
|
||||
|
||||
To verify that a method was called on a spy, we use the ``shouldHaveReceived()``
|
||||
method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived('foo');
|
||||
|
||||
To verify that a method was **not** called on a spy, we use the
|
||||
``shouldNotHaveReceived()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldNotHaveReceived('foo');
|
||||
|
||||
We can also do argument matching with spies:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived('foo')
|
||||
->with('bar');
|
||||
|
||||
Argument matching is also possible by passing in an array of arguments to
|
||||
match:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived('foo', ['bar']);
|
||||
|
||||
Although when verifying a method was not called, the argument matching can only
|
||||
be done by supplying the array of arguments as the 2nd argument to the
|
||||
``shouldNotHaveReceived()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldNotHaveReceived('foo', ['bar']);
|
||||
|
||||
This is due to Mockery's internals.
|
||||
|
||||
Finally, when expecting calls that should have been received, we can also verify
|
||||
the number of calls:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived('foo')
|
||||
->with('bar')
|
||||
->twice();
|
||||
|
||||
Alternative shouldReceive syntax
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As of Mockery 1.0.0, we support calling methods as we would call any PHP method,
|
||||
and not as string arguments to Mockery ``should*`` methods.
|
||||
|
||||
In cases of spies, this only applies to the ``shouldHaveReceived()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived()
|
||||
->foo('bar');
|
||||
|
||||
We can set expectation on number of calls as well:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$spy->shouldHaveReceived()
|
||||
->foo('bar')
|
||||
->twice();
|
||||
|
||||
Unfortunately, due to limitations we can't support the same syntax for the
|
||||
``shouldNotHaveReceived()`` method.
|
||||
@@ -1,230 +0,0 @@
|
||||
.. index::
|
||||
single: Reference; Quick Reference
|
||||
|
||||
Quick Reference
|
||||
===============
|
||||
|
||||
Mockery implements a shorthand API when creating a mock. Here's a sampling of
|
||||
the possible startup methods.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('foo');
|
||||
|
||||
Creates a mock object named "foo". In this case, "foo" is a name (not
|
||||
necessarily a class name) used as a simple identifier when raising exceptions.
|
||||
This creates a mock object of type ``\Mockery\Mock`` and is the loosest form
|
||||
of mock possible.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock(array('foo'=>1,'bar'=>2));
|
||||
|
||||
Creates an mock object named unknown since we passed no name. However we did
|
||||
pass an expectation array, a quick method of setting up methods to expect with
|
||||
their return values.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('foo', array('foo'=>1,'bar'=>2));
|
||||
|
||||
Similar to the previous examples and all examples going forward, expectation
|
||||
arrays can be passed for all mock objects as the second parameter to
|
||||
``mock()``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('foo', function($mock) {
|
||||
$mock->shouldReceive(method_name);
|
||||
});
|
||||
|
||||
In addition to expectation arrays, you can also pass in a closure which
|
||||
contains reusable expectations. This can be passed as the second parameter, or
|
||||
as the third parameter if partnered with an expectation array. This is one
|
||||
method for creating reusable mock expectations.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('stdClass');
|
||||
|
||||
Creates a mock identical to a named mock, except the name is an actual class
|
||||
name. Creates a simple mock as previous examples show, except the mock object
|
||||
will inherit the class type (via inheritance), i.e. it will pass type hints or
|
||||
instanceof evaluations for stdClass. Useful where a mock object must be of a
|
||||
specific type.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('FooInterface');
|
||||
|
||||
You can create mock objects based on any concrete class, abstract class or
|
||||
even an interface. Again, the primary purpose is to ensure the mock object
|
||||
inherits a specific type for type hinting. There is an exception in that
|
||||
classes marked final, or with methods marked final, cannot be mocked fully. In
|
||||
these cases a partial mock (explained later) must be utilised.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('alias:MyNamespace\MyClass');
|
||||
|
||||
Prefixing the valid name of a class (which is NOT currently loaded) with
|
||||
"alias:" will generate an "alias mock". Alias mocks create a class alias with
|
||||
the given classname to stdClass and are generally used to enable the mocking
|
||||
of public static methods. Expectations set on the new mock object which refer
|
||||
to static methods will be used by all static calls to this class.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('overload:MyNamespace\MyClass');
|
||||
|
||||
Prefixing the valid name of a class (which is NOT currently loaded) with
|
||||
"overload:" will generate an alias mock (as with "alias:") except that created
|
||||
new instances of that class will import any expectations set on the origin
|
||||
mock (``$mock``). The origin mock is never verified since it's used an
|
||||
expectation store for new instances. For this purpose we use the term
|
||||
"instance mock" to differentiate it from the simpler "alias mock".
|
||||
|
||||
.. note::
|
||||
|
||||
Using alias/instance mocks across more than one test will generate a fatal
|
||||
error since you can't have two classes of the same name. To avoid this,
|
||||
run each test of this kind in a separate PHP process (which is supported
|
||||
out of the box by both PHPUnit and PHPT).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('stdClass, MyInterface1, MyInterface2');
|
||||
|
||||
The first argument can also accept a list of interfaces that the mock object
|
||||
must implement, optionally including no more than one existing class to be
|
||||
based on. The class name doesn't need to be the first member of the list but
|
||||
it's a friendly convention to use for readability. All subsequent arguments
|
||||
remain unchanged from previous examples.
|
||||
|
||||
If the given class does not exist, you must define and include it beforehand
|
||||
or a ``\Mockery\Exception`` will be thrown.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('MyNamespace\MyClass[foo,bar]');
|
||||
|
||||
The syntax above tells Mockery to partially mock the ``MyNamespace\MyClass``
|
||||
class, by mocking the ``foo()`` and ``bar()`` methods only. Any other method
|
||||
will be not be overridden by Mockery. This traditional form of "partial mock"
|
||||
can be applied to any class or abstract class (e.g. mocking abstract methods
|
||||
where a concrete implementation does not exist yet). If you attempt to partial
|
||||
mock a method marked final, it will actually be ignored in that instance
|
||||
leaving the final method untouched. This is necessary since mocking of final
|
||||
methods is, by definition in PHP, impossible.
|
||||
|
||||
Please refer to ":doc:`partial_mocks`" for a detailed explanation on how to
|
||||
create Partial Mocks in Mockery.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock("MyNamespace\MyClass[foo]", array($arg1, $arg2));
|
||||
|
||||
If Mockery encounters an indexed array as the second or third argument, it
|
||||
will assume they are constructor parameters and pass them when constructing
|
||||
the mock object. The syntax above will create a new partial mock, particularly
|
||||
useful if method ``bar`` calls method ``foo`` internally with
|
||||
``$this->foo()``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock(new Foo);
|
||||
|
||||
Passing any real object into Mockery will create a Proxied Partial Mock. This
|
||||
can be useful if real partials are impossible, e.g. a final class or class
|
||||
where you absolutely must override a method marked final. Since you can
|
||||
already create a concrete object, so all we need to do is selectively override
|
||||
a subset of existing methods (or add non-existing methods!) for our
|
||||
expectations.
|
||||
|
||||
A little revision: All mock methods accept the class, object or alias name to
|
||||
be mocked as the first parameter. The second parameter can be an expectation
|
||||
array of methods and their return values, or an expectation closure (which can
|
||||
be the third param if used in conjunction with an expectation array).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::self()
|
||||
|
||||
At times, you will discover that expectations on a mock include methods which
|
||||
need to return the same mock object (e.g. a common case when designing a
|
||||
Domain Specific Language (DSL) such as the one Mockery itself uses!). To
|
||||
facilitate this, calling ``\Mockery::self()`` will always return the last Mock
|
||||
Object created by calling ``\Mockery::mock()``. For example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::mock('BazIterator')
|
||||
->shouldReceive('next')
|
||||
->andReturn(\Mockery::self())
|
||||
->mock();
|
||||
|
||||
The above class being mocked, as the ``next()`` method suggests, is an
|
||||
iterator. In many cases, you can replace all the iterated elements (since they
|
||||
are the same type many times) with just the one mock object which is
|
||||
programmed to act as discrete iterated elements.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$mock = \Mockery::namedMock('MyClassName', 'DateTime');
|
||||
|
||||
The ``namedMock`` method will generate a class called by the first argument,
|
||||
so in this example ``MyClassName``. The rest of the arguments are treat in the
|
||||
same way as the ``mock`` method, so again, this example would create a class
|
||||
called ``MyClassName`` that extends ``DateTime``.
|
||||
|
||||
Named mocks are quite an edge case, but they can be useful when code depends
|
||||
on the ``__CLASS__`` magic constant, or when you need two derivatives of an
|
||||
abstract type, that are actually different classes.
|
||||
|
||||
.. caution::
|
||||
|
||||
You can only create a named mock once, any subsequent calls to
|
||||
``namedMock``, with different arguments are likely to cause exceptions.
|
||||
|
||||
Behaviour Modifiers
|
||||
-------------------
|
||||
|
||||
When creating a mock object, you may wish to use some commonly preferred
|
||||
behaviours that are not the default in Mockery.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::mock('MyClass')->shouldIgnoreMissing()
|
||||
|
||||
The use of the ``shouldIgnoreMissing()`` behaviour modifier will label this
|
||||
mock object as a Passive Mock. In such a mock object, calls to methods which
|
||||
are not covered by expectations will return ``null`` instead of the usual
|
||||
complaining about there being no expectation matching the call.
|
||||
|
||||
You can optionally prefer to return an object of type ``\Mockery\Undefined``
|
||||
(i.e. a ``null`` object) (which was the 0.7.2 behaviour) by using an
|
||||
additional modifier:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\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
|
||||
logic check.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::mock('MyClass')->makePartial()
|
||||
|
||||
also
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
\Mockery::mock('MyClass')->shouldDeferMissing()
|
||||
|
||||
Known as a Passive Partial Mock (not to be confused with real partial mock
|
||||
objects discussed later), this form of mock object will defer all methods not
|
||||
subject to an expectation to the parent class of the mock, i.e. ``MyClass``.
|
||||
Whereas the previous ``shouldIgnoreMissing()`` returned ``null``, this
|
||||
behaviour simply calls the parent's matching method.
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(
|
||||
dirname(__FILE__) . '/../../library'
|
||||
. PATH_SEPARATOR . get_include_path()
|
||||
);
|
||||
|
||||
require_once 'Mockery/Loader.php';
|
||||
|
||||
$loader = new \Mockery\Loader;
|
||||
$loader->register();
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Starship
|
||||
{
|
||||
|
||||
protected $_engineering = null;
|
||||
|
||||
public function __construct($engineering)
|
||||
{
|
||||
$this->_engineering = $engineering;
|
||||
}
|
||||
|
||||
public function enterOrbit()
|
||||
{
|
||||
$this->_engineering->disengageWarp();
|
||||
$this->_engineering->runDiagnosticLevel(5);
|
||||
$this->_engineering->divertPower(0.40, 'sensors');
|
||||
$this->_engineering->divertPower(0.30, 'auxengines');
|
||||
$this->_engineering->runDiagnosticLevel(1);
|
||||
|
||||
// We can add more runDiagnosticLevel() calls without failing the test
|
||||
// anywhere above since they are unordered.
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
use \Mockery as M;
|
||||
|
||||
require_once 'Starship.php';
|
||||
|
||||
class StarshipTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testEngineeringResponseToEnteringOrbit()
|
||||
{
|
||||
$mock = M::mock('Engineering');
|
||||
$mock->shouldReceive('disengageWarp')->once()->ordered();
|
||||
$mock->shouldReceive('divertPower')->with(0.40, 'sensors')->once()->ordered();
|
||||
$mock->shouldReceive('divertPower')->with(0.30, 'auxengines')->once()->ordered();
|
||||
$mock->shouldReceive('runDiagnosticLevel')->with(1)->once()->ordered();
|
||||
$mock->shouldReceive('runDiagnosticLevel')->with(M::type('int'))->zeroOrMoreTimes();
|
||||
|
||||
$starship = new Starship($mock);
|
||||
$starship->enterOrbit();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<phpunit bootstrap="./Bootstrap.php">
|
||||
<testsuite name="Starship Test Suite">
|
||||
<directory>./</directory>
|
||||
</testsuite>
|
||||
<listeners>
|
||||
<listener class="\Mockery\Adapter\Phpunit\TestListener"
|
||||
file="Mockery/Adapter/Phpunit/TestListener.php">
|
||||
</listener>
|
||||
</listeners>
|
||||
</phpunit>
|
||||
460
vendor/mockery/mockery/library/Mockery.php
vendored
460
vendor/mockery/mockery/library/Mockery.php
vendored
@@ -14,25 +14,21 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
use Mockery\ClosureWrapper;
|
||||
use Mockery\ExpectationInterface;
|
||||
use Mockery\Generator\CachingGenerator;
|
||||
use Mockery\Generator\Generator;
|
||||
use Mockery\Generator\MockConfigurationBuilder;
|
||||
use Mockery\Generator\MockNameBuilder;
|
||||
use Mockery\Generator\StringManipulationGenerator;
|
||||
use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
|
||||
use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
|
||||
use Mockery\Generator\StringManipulation\Pass\ClassPass;
|
||||
use Mockery\Generator\StringManipulation\Pass\InstanceMockPass;
|
||||
use Mockery\Generator\StringManipulation\Pass\InterfacePass;
|
||||
use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass;
|
||||
use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass;
|
||||
use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass;
|
||||
use Mockery\Loader\EvalLoader;
|
||||
use Mockery\Loader\Loader;
|
||||
use Mockery\Matcher\MatcherAbstract;
|
||||
use Mockery\Reflector;
|
||||
|
||||
class Mockery
|
||||
{
|
||||
@@ -41,7 +37,7 @@ class Mockery
|
||||
/**
|
||||
* Global container to hold all mocks for the current unit test running.
|
||||
*
|
||||
* @var \Mockery\Container
|
||||
* @var \Mockery\Container|null
|
||||
*/
|
||||
protected static $_container = null;
|
||||
|
||||
@@ -65,47 +61,100 @@ class Mockery
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $_filesToCleanUp = array();
|
||||
private static $_filesToCleanUp = [];
|
||||
|
||||
/**
|
||||
* Defines the global helper functions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function globalHelpers()
|
||||
{
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*
|
||||
* @deprecated since 1.3.2 and will be removed in 2.0.
|
||||
*/
|
||||
public static function builtInTypes()
|
||||
{
|
||||
return array(
|
||||
'array',
|
||||
'bool',
|
||||
'callable',
|
||||
'float',
|
||||
'int',
|
||||
'iterable',
|
||||
'object',
|
||||
'self',
|
||||
'string',
|
||||
'void',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated since 1.3.2 and will be removed in 2.0.
|
||||
*/
|
||||
public static function isBuiltInType($type)
|
||||
{
|
||||
return in_array($type, \Mockery::builtInTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Static shortcut to \Mockery\Container::mock().
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @param mixed ...$args
|
||||
*
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public static function mock()
|
||||
public static function mock(...$args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func_array(array(self::getContainer(), 'mock'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Mockery\MockInterface
|
||||
* Static and semantic shortcut for getting a mock from the container
|
||||
* and applying the spy's expected behavior into it.
|
||||
*
|
||||
* @param mixed ...$args
|
||||
*
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public static function spy()
|
||||
public static function spy(...$args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
if (count($args) && $args[0] instanceof \Closure) {
|
||||
$args[0] = new ClosureWrapper($args[0]);
|
||||
}
|
||||
|
||||
return call_user_func_array(array(self::getContainer(), 'mock'), $args)->shouldIgnoreMissing();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Mockery\MockInterface
|
||||
* Static and Semantic shortcut to \Mockery\Container::mock().
|
||||
*
|
||||
* @param mixed ...$args
|
||||
*
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public static function instanceMock()
|
||||
public static function instanceMock(...$args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func_array(array(self::getContainer(), 'mock'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static shortcut to \Mockery\Container::mock(), first argument names the mock.
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @param mixed ...$args
|
||||
*
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public static function namedMock()
|
||||
public static function namedMock(...$args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$name = array_shift($args);
|
||||
|
||||
$builder = new MockConfigurationBuilder();
|
||||
@@ -121,7 +170,7 @@ class Mockery
|
||||
*
|
||||
* @throws LogicException
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public static function self()
|
||||
{
|
||||
@@ -143,31 +192,36 @@ class Mockery
|
||||
foreach (self::$_filesToCleanUp as $fileName) {
|
||||
@unlink($fileName);
|
||||
}
|
||||
self::$_filesToCleanUp = array();
|
||||
self::$_filesToCleanUp = [];
|
||||
|
||||
if (is_null(self::$_container)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$_container->mockery_teardown();
|
||||
self::$_container->mockery_close();
|
||||
$container = self::$_container;
|
||||
self::$_container = null;
|
||||
|
||||
$container->mockery_teardown();
|
||||
$container->mockery_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Static fetching of a mock associated with a name or explicit class poser.
|
||||
*
|
||||
* @param $name
|
||||
* @param string $name
|
||||
*
|
||||
* @return \Mockery\Mock
|
||||
*/
|
||||
public static function fetchMock($name)
|
||||
{
|
||||
return self::$_container->fetchMock($name);
|
||||
return self::getContainer()->fetchMock($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the container.
|
||||
* Lazy loader and getter for
|
||||
* the container property.
|
||||
*
|
||||
* @return Mockery\Container
|
||||
*/
|
||||
public static function getContainer()
|
||||
{
|
||||
@@ -179,6 +233,8 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the $_generator static property.
|
||||
*
|
||||
* @param \Mockery\Generator\Generator $generator
|
||||
*/
|
||||
public static function setGenerator(Generator $generator)
|
||||
@@ -186,6 +242,12 @@ class Mockery
|
||||
self::$_generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy loader method and getter for
|
||||
* the generator property.
|
||||
*
|
||||
* @return Generator
|
||||
*/
|
||||
public static function getGenerator()
|
||||
{
|
||||
if (is_null(self::$_generator)) {
|
||||
@@ -195,23 +257,20 @@ class Mockery
|
||||
return self::$_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a default generator
|
||||
* used inside this class.
|
||||
*
|
||||
* @return CachingGenerator
|
||||
*/
|
||||
public static function getDefaultGenerator()
|
||||
{
|
||||
$generator = new StringManipulationGenerator(array(
|
||||
new CallTypeHintPass(),
|
||||
new ClassPass(),
|
||||
new ClassNamePass(),
|
||||
new InstanceMockPass(),
|
||||
new InterfacePass(),
|
||||
new MethodDefinitionPass(),
|
||||
new RemoveUnserializeForInternalSerializableClassesPass(),
|
||||
new RemoveBuiltinMethodsThatAreFinalPass(),
|
||||
));
|
||||
|
||||
return new CachingGenerator($generator);
|
||||
return new CachingGenerator(StringManipulationGenerator::withDefaultPasses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the $_loader static property.
|
||||
*
|
||||
* @param Loader $loader
|
||||
*/
|
||||
public static function setLoader(Loader $loader)
|
||||
@@ -220,6 +279,9 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy loader method and getter for
|
||||
* the $_loader property.
|
||||
*
|
||||
* @return Loader
|
||||
*/
|
||||
public static function getLoader()
|
||||
@@ -232,6 +294,8 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an EvalLoader to be used as default.
|
||||
*
|
||||
* @return EvalLoader
|
||||
*/
|
||||
public static function getDefaultLoader()
|
||||
@@ -253,6 +317,8 @@ class Mockery
|
||||
|
||||
/**
|
||||
* Reset the container to null.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resetContainer()
|
||||
{
|
||||
@@ -269,10 +335,33 @@ class Mockery
|
||||
return new \Mockery\Matcher\Any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of AndAnyOtherArgs matcher.
|
||||
*
|
||||
* An alternative name to `andAnyOtherArgs` so
|
||||
* the API stays closer to `any` as well.
|
||||
*
|
||||
* @return \Mockery\Matcher\AndAnyOtherArgs
|
||||
*/
|
||||
public static function andAnyOthers()
|
||||
{
|
||||
return new \Mockery\Matcher\AndAnyOtherArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of AndAnyOtherArgs matcher.
|
||||
*
|
||||
* @return \Mockery\Matcher\AndAnyOtherArgs
|
||||
*/
|
||||
public static function andAnyOtherArgs()
|
||||
{
|
||||
return new \Mockery\Matcher\AndAnyOtherArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of TYPE matcher.
|
||||
*
|
||||
* @param $expected
|
||||
* @param mixed $expected
|
||||
*
|
||||
* @return \Mockery\Matcher\Type
|
||||
*/
|
||||
@@ -284,39 +373,44 @@ class Mockery
|
||||
/**
|
||||
* Return instance of DUCKTYPE matcher.
|
||||
*
|
||||
* @param array ...$args
|
||||
*
|
||||
* @return \Mockery\Matcher\Ducktype
|
||||
*/
|
||||
public static function ducktype()
|
||||
public static function ducktype(...$args)
|
||||
{
|
||||
return new \Mockery\Matcher\Ducktype(func_get_args());
|
||||
return new \Mockery\Matcher\Ducktype($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of SUBSET matcher.
|
||||
*
|
||||
* @param array $part
|
||||
* @param bool $strict - (Optional) True for strict comparison, false for loose
|
||||
*
|
||||
* @return \Mockery\Matcher\Subset
|
||||
*/
|
||||
public static function subset(array $part)
|
||||
public static function subset(array $part, $strict = true)
|
||||
{
|
||||
return new \Mockery\Matcher\Subset($part);
|
||||
return new \Mockery\Matcher\Subset($part, $strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of CONTAINS matcher.
|
||||
*
|
||||
* @param mixed $args
|
||||
*
|
||||
* @return \Mockery\Matcher\Contains
|
||||
*/
|
||||
public static function contains()
|
||||
public static function contains(...$args)
|
||||
{
|
||||
return new \Mockery\Matcher\Contains(func_get_args());
|
||||
return new \Mockery\Matcher\Contains($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of HASKEY matcher.
|
||||
*
|
||||
* @param $key
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return \Mockery\Matcher\HasKey
|
||||
*/
|
||||
@@ -328,7 +422,7 @@ class Mockery
|
||||
/**
|
||||
* Return instance of HASVALUE matcher.
|
||||
*
|
||||
* @param $val
|
||||
* @param mixed $val
|
||||
*
|
||||
* @return \Mockery\Matcher\HasValue
|
||||
*/
|
||||
@@ -340,7 +434,24 @@ class Mockery
|
||||
/**
|
||||
* Return instance of CLOSURE matcher.
|
||||
*
|
||||
* @param $closure
|
||||
* @param $reference
|
||||
*
|
||||
* @return \Mockery\Matcher\Closure
|
||||
*/
|
||||
public static function capture(&$reference)
|
||||
{
|
||||
$closure = function ($argument) use (&$reference) {
|
||||
$reference = $argument;
|
||||
return true;
|
||||
};
|
||||
|
||||
return new \Mockery\Matcher\Closure($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of CLOSURE matcher.
|
||||
*
|
||||
* @param mixed $closure
|
||||
*
|
||||
* @return \Mockery\Matcher\Closure
|
||||
*/
|
||||
@@ -352,7 +463,7 @@ class Mockery
|
||||
/**
|
||||
* Return instance of MUSTBE matcher.
|
||||
*
|
||||
* @param $expected
|
||||
* @param mixed $expected
|
||||
*
|
||||
* @return \Mockery\Matcher\MustBe
|
||||
*/
|
||||
@@ -364,7 +475,7 @@ class Mockery
|
||||
/**
|
||||
* Return instance of NOT matcher.
|
||||
*
|
||||
* @param $expected
|
||||
* @param mixed $expected
|
||||
*
|
||||
* @return \Mockery\Matcher\Not
|
||||
*/
|
||||
@@ -376,25 +487,44 @@ class Mockery
|
||||
/**
|
||||
* Return instance of ANYOF matcher.
|
||||
*
|
||||
* @param array ...$args
|
||||
*
|
||||
* @return \Mockery\Matcher\AnyOf
|
||||
*/
|
||||
public static function anyOf()
|
||||
public static function anyOf(...$args)
|
||||
{
|
||||
return new \Mockery\Matcher\AnyOf(func_get_args());
|
||||
return new \Mockery\Matcher\AnyOf($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of NOTANYOF matcher.
|
||||
*
|
||||
* @param array ...$args
|
||||
*
|
||||
* @return \Mockery\Matcher\NotAnyOf
|
||||
*/
|
||||
public static function notAnyOf()
|
||||
public static function notAnyOf(...$args)
|
||||
{
|
||||
return new \Mockery\Matcher\NotAnyOf(func_get_args());
|
||||
return new \Mockery\Matcher\NotAnyOf($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global configuration container.
|
||||
* Return instance of PATTERN matcher.
|
||||
*
|
||||
* @param mixed $expected
|
||||
*
|
||||
* @return \Mockery\Matcher\Pattern
|
||||
*/
|
||||
public static function pattern($expected)
|
||||
{
|
||||
return new \Mockery\Matcher\Pattern($expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy loader and Getter for the global
|
||||
* configuration container.
|
||||
*
|
||||
* @return \Mockery\Configuration
|
||||
*/
|
||||
public static function getConfiguration()
|
||||
{
|
||||
@@ -427,8 +557,21 @@ class Mockery
|
||||
return $method . '(' . implode(', ', $formattedArguments) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation
|
||||
* of any passed argument.
|
||||
*
|
||||
* @param mixed $argument
|
||||
* @param int $depth
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function formatArgument($argument, $depth = 0)
|
||||
{
|
||||
if ($argument instanceof MatcherAbstract) {
|
||||
return (string) $argument;
|
||||
}
|
||||
|
||||
if (is_object($argument)) {
|
||||
return 'object(' . get_class($argument) . ')';
|
||||
}
|
||||
@@ -439,16 +582,19 @@ class Mockery
|
||||
|
||||
if (is_array($argument)) {
|
||||
if ($depth === 1) {
|
||||
$argument = 'array(...)';
|
||||
$argument = '[...]';
|
||||
} else {
|
||||
$sample = array();
|
||||
foreach ($argument as $key => $value) {
|
||||
$sample[$key] = self::formatArgument($value, $depth + 1);
|
||||
$key = is_int($key) ? $key : "'$key'";
|
||||
$value = self::formatArgument($value, $depth + 1);
|
||||
$sample[] = "$key => $value";
|
||||
}
|
||||
$argument = preg_replace("{\s}", '', var_export($sample, true));
|
||||
|
||||
$argument = "[" . implode(", ", $sample) . "]";
|
||||
}
|
||||
|
||||
return ((strlen($argument) > 1000) ? substr($argument, 0, 1000).'...)' : $argument);
|
||||
return ((strlen($argument) > 1000) ? substr($argument, 0, 1000) . '...]' : $argument);
|
||||
}
|
||||
|
||||
if (is_bool($argument)) {
|
||||
@@ -463,9 +609,7 @@ class Mockery
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
$argument = (string) $argument;
|
||||
|
||||
return $depth === 0 ? '"' . $argument . '"' : $argument;
|
||||
return "'" . (string) $argument . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,7 +651,7 @@ class Mockery
|
||||
/**
|
||||
* Utility function to turn public properties and public get* and is* method values into an array.
|
||||
*
|
||||
* @param $object
|
||||
* @param object $object
|
||||
* @param int $nesting
|
||||
*
|
||||
* @return array
|
||||
@@ -518,18 +662,29 @@ class Mockery
|
||||
return array('...');
|
||||
}
|
||||
|
||||
return array(
|
||||
'class' => get_class($object),
|
||||
'properties' => self::extractInstancePublicProperties($object, $nesting),
|
||||
'getters' => self::extractGetters($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all public instance properties.
|
||||
*
|
||||
* @param $object
|
||||
* @param $nesting
|
||||
* @param mixed $object
|
||||
* @param int $nesting
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -542,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,39 +709,14 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all object getters.
|
||||
* Utility method used for recursively generating
|
||||
* an object or array representation.
|
||||
*
|
||||
* @param $object
|
||||
* @param $nesting
|
||||
* @param mixed $argument
|
||||
* @param int $nesting
|
||||
*
|
||||
* @return array
|
||||
* @return mixed
|
||||
*/
|
||||
private static function extractGetters($object, $nesting)
|
||||
{
|
||||
$reflection = new \ReflectionClass(get_class($object));
|
||||
$publicMethods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
$getters = array();
|
||||
|
||||
foreach ($publicMethods as $publicMethod) {
|
||||
$name = $publicMethod->getName();
|
||||
$irrelevantName = (substr($name, 0, 3) !== 'get' && substr($name, 0, 2) !== 'is');
|
||||
$isStatic = $publicMethod->isStatic();
|
||||
$numberOfParameters = $publicMethod->getNumberOfParameters();
|
||||
|
||||
if ($irrelevantName || $numberOfParameters != 0 || $isStatic) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$getters[$name] = self::cleanupNesting($object->$name(), $nesting);
|
||||
} catch (\Exception $e) {
|
||||
$getters[$name] = '!! ' . get_class($e) . ': ' . $e->getMessage() . ' !!';
|
||||
}
|
||||
}
|
||||
|
||||
return $getters;
|
||||
}
|
||||
|
||||
private static function cleanupNesting($argument, $nesting)
|
||||
{
|
||||
if (is_object($argument)) {
|
||||
@@ -599,6 +733,16 @@ class Mockery
|
||||
return $argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for recursively
|
||||
* gerating a representation
|
||||
* of the given array.
|
||||
*
|
||||
* @param array $argument
|
||||
* @param int $nesting
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function cleanupArray($argument, $nesting = 3)
|
||||
{
|
||||
if ($nesting == 0) {
|
||||
@@ -620,12 +764,12 @@ class Mockery
|
||||
* Utility function to parse shouldReceive() arguments and generate
|
||||
* expectations from such as needed.
|
||||
*
|
||||
* @param Mockery\MockInterface $mock
|
||||
* @param array $args
|
||||
* @param Mockery\LegacyMockInterface $mock
|
||||
* @param array ...$args
|
||||
* @param callable $add
|
||||
* @return \Mockery\CompositeExpectation
|
||||
*/
|
||||
public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add)
|
||||
public static function parseShouldReturnArgs(\Mockery\LegacyMockInterface $mock, $args, $add)
|
||||
{
|
||||
$composite = new \Mockery\CompositeExpectation();
|
||||
|
||||
@@ -648,13 +792,13 @@ class Mockery
|
||||
* Sets up expectations on the members of the CompositeExpectation and
|
||||
* builds up any demeter chain that was passed to shouldReceive.
|
||||
*
|
||||
* @param \Mockery\MockInterface $mock
|
||||
* @param \Mockery\LegacyMockInterface $mock
|
||||
* @param string $arg
|
||||
* @param callable $add
|
||||
* @throws Mockery\Exception
|
||||
* @return \Mockery\ExpectationDirector
|
||||
* @return \Mockery\ExpectationInterface
|
||||
*/
|
||||
protected static function buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add)
|
||||
protected static function buildDemeterChain(\Mockery\LegacyMockInterface $mock, $arg, $add)
|
||||
{
|
||||
/** @var Mockery\Container $container */
|
||||
$container = $mock->mockery_getContainer();
|
||||
@@ -680,6 +824,8 @@ class Mockery
|
||||
return $add($method);
|
||||
};
|
||||
|
||||
$parent = get_class($mock);
|
||||
|
||||
while (true) {
|
||||
$method = array_shift($methodNames);
|
||||
$expectations = $mock->mockery_getExpectationsFor($method);
|
||||
@@ -690,14 +836,16 @@ class Mockery
|
||||
break;
|
||||
}
|
||||
|
||||
$mock = self::getNewDemeterMock($container, $method, $expectations);
|
||||
$mock = self::getNewDemeterMock($container, $parent, $method, $expectations);
|
||||
} else {
|
||||
$demeterMockKey = $container->getKeyOfDemeterMockFor($method);
|
||||
$demeterMockKey = $container->getKeyOfDemeterMockFor($method, $parent);
|
||||
if ($demeterMockKey) {
|
||||
$mock = self::getExistingDemeterMock($container, $demeterMockKey);
|
||||
}
|
||||
}
|
||||
|
||||
$parent .= '->' . $method;
|
||||
|
||||
$nextExp = function ($n) use ($mock) {
|
||||
return $mock->shouldReceive($n);
|
||||
};
|
||||
@@ -707,30 +855,66 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new demeter configured
|
||||
* mock from the container.
|
||||
*
|
||||
* @param \Mockery\Container $container
|
||||
* @param string $parent
|
||||
* @param string $method
|
||||
* @param Mockery\ExpectationInterface $exp
|
||||
*
|
||||
* @return \Mockery\Mock
|
||||
*/
|
||||
private static function getNewDemeterMock(Mockery\Container $container,
|
||||
private static function getNewDemeterMock(
|
||||
Mockery\Container $container,
|
||||
$parent,
|
||||
$method,
|
||||
Mockery\ExpectationInterface $exp
|
||||
) {
|
||||
$mock = $container->mock('demeter_' . $method);
|
||||
$newMockName = 'demeter_' . md5($parent) . '_' . $method;
|
||||
|
||||
$parRef = null;
|
||||
$parRefMethod = null;
|
||||
$parRefMethodRetType = null;
|
||||
|
||||
$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 ($parRefMethodRetType !== null && $parRefMethodRetType !== 'mixed') {
|
||||
$nameBuilder = new MockNameBuilder();
|
||||
$nameBuilder->addPart('\\' . $newMockName);
|
||||
$mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType);
|
||||
$exp->andReturn($mock);
|
||||
|
||||
return $mock;
|
||||
}
|
||||
}
|
||||
|
||||
$mock = $container->mock($newMockName);
|
||||
$exp->andReturn($mock);
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an specific demeter mock from
|
||||
* the ones kept by the container.
|
||||
*
|
||||
* @param \Mockery\Container $container
|
||||
* @param string $demeterMockKey
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function getExistingDemeterMock(Mockery\Container $container, $demeterMockKey)
|
||||
{
|
||||
private static function getExistingDemeterMock(
|
||||
Mockery\Container $container,
|
||||
$demeterMockKey
|
||||
) {
|
||||
$mocks = $container->getMocks();
|
||||
$mock = $mocks[$demeterMockKey];
|
||||
|
||||
@@ -738,6 +922,9 @@ class Mockery
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the passed array representing a demeter
|
||||
* chain with the method names is empty.
|
||||
*
|
||||
* @param array $methodNames
|
||||
*
|
||||
* @return bool
|
||||
@@ -747,6 +934,43 @@ class Mockery
|
||||
return empty($methodNames);
|
||||
}
|
||||
|
||||
public static function declareClass($fqn)
|
||||
{
|
||||
return static::declareType($fqn, "class");
|
||||
}
|
||||
|
||||
public static function declareInterface($fqn)
|
||||
{
|
||||
return static::declareType($fqn, "interface");
|
||||
}
|
||||
|
||||
private static function declareType($fqn, $type)
|
||||
{
|
||||
$targetCode = "<?php ";
|
||||
$shortName = $fqn;
|
||||
|
||||
if (strpos($fqn, "\\")) {
|
||||
$parts = explode("\\", $fqn);
|
||||
|
||||
$shortName = trim(array_pop($parts));
|
||||
$namespace = implode("\\", $parts);
|
||||
|
||||
$targetCode.= "namespace $namespace;\n";
|
||||
}
|
||||
|
||||
$targetCode.= "$type $shortName {} ";
|
||||
|
||||
/*
|
||||
* We could eval here, but it doesn't play well with the way
|
||||
* PHPUnit tries to backup global state and the require definition
|
||||
* loader
|
||||
*/
|
||||
$tmpfname = tempnam(sys_get_temp_dir(), "Mockery");
|
||||
file_put_contents($tmpfname, $targetCode);
|
||||
require $tmpfname;
|
||||
\Mockery::registerFileForCleanUp($tmpfname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a file to be deleted on tearDown.
|
||||
*
|
||||
|
||||
@@ -1,26 +1,90 @@
|
||||
<?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;
|
||||
|
||||
use Mockery;
|
||||
|
||||
/**
|
||||
* Integrates Mockery into PHPUnit. Ensures Mockery expectations are verified
|
||||
* for each test and are included by the assertion counter.
|
||||
*/
|
||||
trait MockeryPHPUnitIntegration
|
||||
{
|
||||
use MockeryPHPUnitIntegrationAssertPostConditions;
|
||||
|
||||
protected $mockeryOpen;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected function assertPostConditions()
|
||||
protected function mockeryAssertPostConditions()
|
||||
{
|
||||
parent::assertPostConditions();
|
||||
$this->addMockeryExpectationsToAssertionCount();
|
||||
$this->checkMockeryExceptions();
|
||||
$this->closeMockery();
|
||||
|
||||
// Add Mockery expectations to assertion count.
|
||||
if (($container = \Mockery::getContainer()) !== null) {
|
||||
$this->addToAssertionCount($container->mockery_getExpectationCount());
|
||||
parent::assertPostConditions();
|
||||
}
|
||||
|
||||
protected function addMockeryExpectationsToAssertionCount()
|
||||
{
|
||||
$this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount());
|
||||
}
|
||||
|
||||
protected function checkMockeryExceptions()
|
||||
{
|
||||
if (!method_exists($this, "markAsRisky")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify Mockery expectations.
|
||||
\Mockery::close();
|
||||
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
|
||||
*/
|
||||
protected function purgeMockeryContainer()
|
||||
{
|
||||
if ($this->mockeryOpen) {
|
||||
// post conditions wasn't called, so test probably failed
|
||||
Mockery::close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mockery\Adapter\Phpunit;
|
||||
|
||||
trait MockeryPHPUnitIntegrationAssertPostConditions
|
||||
{
|
||||
protected function assertPostConditions(): void
|
||||
{
|
||||
$this->mockeryAssertPostConditions();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,35 @@
|
||||
<?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;
|
||||
|
||||
use Mockery;
|
||||
|
||||
abstract class MockeryTestCase extends \PHPUnit_Framework_TestCase
|
||||
abstract class MockeryTestCase extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function assertPostConditions()
|
||||
{
|
||||
$this->addMockeryExpectationsToAssertionCount();
|
||||
$this->closeMockery();
|
||||
use MockeryPHPUnitIntegration;
|
||||
use MockeryTestCaseSetUp;
|
||||
|
||||
parent::assertPostConditions();
|
||||
protected function mockeryTestSetUp()
|
||||
{
|
||||
}
|
||||
|
||||
protected function addMockeryExpectationsToAssertionCount()
|
||||
protected function mockeryTestTearDown()
|
||||
{
|
||||
$container = Mockery::getContainer();
|
||||
if ($container != null) {
|
||||
$count = $container->mockery_getExpectationCount();
|
||||
$this->addToAssertionCount($count);
|
||||
}
|
||||
}
|
||||
|
||||
protected function closeMockery()
|
||||
{
|
||||
Mockery::close();
|
||||
}
|
||||
}
|
||||
|
||||
38
vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCaseSetUp.php
vendored
Normal file
38
vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCaseSetUp.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mockery\Adapter\Phpunit;
|
||||
|
||||
trait MockeryTestCaseSetUp
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockeryTestSetUp();
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->mockeryTestTearDown();
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
@@ -12,82 +12,37 @@
|
||||
* 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-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
* @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;
|
||||
|
||||
class TestListener implements \PHPUnit_Framework_TestListener
|
||||
use PHPUnit\Framework\Test;
|
||||
use PHPUnit\Framework\TestListenerDefaultImplementation;
|
||||
use PHPUnit\Framework\TestSuite;
|
||||
use PHPUnit\Framework\TestListener as PHPUnitTestListener;
|
||||
|
||||
class TestListener implements PHPUnitTestListener
|
||||
{
|
||||
use TestListenerDefaultImplementation;
|
||||
|
||||
/**
|
||||
* After each test, perform Mockery verification tasks and cleanup the
|
||||
* statically stored Mockery container for the next test.
|
||||
*
|
||||
* @param PHPUnit_Framework_Test $test
|
||||
* @param float $time
|
||||
*/
|
||||
public function endTest(\PHPUnit_Framework_Test $test, $time)
|
||||
private $trait;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
$container = \Mockery::getContainer();
|
||||
// check addToAssertionCount is important to avoid mask test errors
|
||||
if ($container != null && method_exists($test, 'addToAssertionCount')) {
|
||||
$expectation_count = $container->mockery_getExpectationCount();
|
||||
$test->addToAssertionCount($expectation_count);
|
||||
}
|
||||
\Mockery::close();
|
||||
} catch (\Exception $e) {
|
||||
$result = $test->getTestResultObject();
|
||||
$result->addError($test, $e, $time);
|
||||
}
|
||||
$this->trait = new TestListenerTrait();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Mockery files to PHPUnit's blacklist so they don't showup on coverage reports
|
||||
*/
|
||||
public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
|
||||
{
|
||||
if (class_exists('\\PHP_CodeCoverage_Filter')
|
||||
&& method_exists('\\PHP_CodeCoverage_Filter', 'getInstance')) {
|
||||
\PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist(
|
||||
__DIR__.'/../../../Mockery/', '.php', '', 'PHPUNIT'
|
||||
);
|
||||
|
||||
\PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__DIR__.'/../../../Mockery.php', 'PHPUNIT');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The Listening methods below are not required for Mockery
|
||||
*/
|
||||
public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
public function endTest(Test $test, float $time): void
|
||||
{
|
||||
$this->trait->endTest($test, $time);
|
||||
}
|
||||
|
||||
public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
|
||||
{
|
||||
}
|
||||
|
||||
public function startTest(\PHPUnit_Framework_Test $test)
|
||||
public function startTestSuite(TestSuite $suite): void
|
||||
{
|
||||
$this->trait->startTestSuite();
|
||||
}
|
||||
}
|
||||
|
||||
87
vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListenerTrait.php
vendored
Normal file
87
vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListenerTrait.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?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;
|
||||
|
||||
use PHPUnit\Framework\ExpectationFailedException;
|
||||
use PHPUnit\Framework\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Util\Blacklist;
|
||||
use PHPUnit\Runner\BaseTestRunner;
|
||||
|
||||
class TestListenerTrait
|
||||
{
|
||||
/**
|
||||
* endTest is called after each test and checks if \Mockery::close() has
|
||||
* been called, and will let the test fail if it hasn't.
|
||||
*
|
||||
* @param Test $test
|
||||
* @param float $time
|
||||
*/
|
||||
public function endTest(Test $test, $time)
|
||||
{
|
||||
if (!$test instanceof TestCase) {
|
||||
// We need the getTestResultObject and getStatus methods which are
|
||||
// not part of the interface.
|
||||
return;
|
||||
}
|
||||
|
||||
if ($test->getStatus() !== BaseTestRunner::STATUS_PASSED) {
|
||||
// If the test didn't pass there is no guarantee that
|
||||
// verifyMockObjects and assertPostConditions have been called.
|
||||
// And even if it did, the point here is to prevent false
|
||||
// negatives, not to make failing tests fail for more reasons.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// The self() call is used as a sentinel. Anything that throws if
|
||||
// the container is closed already will do.
|
||||
\Mockery::self();
|
||||
} catch (\LogicException $_) {
|
||||
return;
|
||||
}
|
||||
|
||||
$e = new ExpectationFailedException(
|
||||
\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__
|
||||
)
|
||||
);
|
||||
|
||||
/** @var \PHPUnit\Framework\TestResult $result */
|
||||
$result = $test->getTestResultObject();
|
||||
|
||||
if ($result !== null) {
|
||||
$result->addFailure($test, $e, $time);
|
||||
}
|
||||
}
|
||||
|
||||
public function startTestSuite()
|
||||
{
|
||||
if (method_exists(Blacklist::class, 'addDirectory')) {
|
||||
(new BlackList())->getBlacklistedDirectories();
|
||||
Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName()));
|
||||
} else {
|
||||
Blacklist::$blacklistedClassNames[\Mockery::class] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
vendor/mockery/mockery/library/Mockery/ClosureWrapper.php
vendored
Normal file
42
vendor/mockery/mockery/library/Mockery/ClosureWrapper.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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) 2017 Dave Marshall https://github.com/davedevelopment
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
namespace Mockery;
|
||||
|
||||
use Mockery\Matcher\Closure;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ClosureWrapper
|
||||
{
|
||||
private $closure;
|
||||
|
||||
public function __construct(\Closure $closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
public function __invoke()
|
||||
{
|
||||
return call_user_func_array($this->closure, func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Mockery;
|
||||
|
||||
class CompositeExpectation implements ExpectationInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Stores an array of all expectations for this composite
|
||||
*
|
||||
@@ -42,11 +41,22 @@ class CompositeExpectation implements ExpectationInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed ...
|
||||
* @param mixed ...$args
|
||||
*/
|
||||
public function andReturn()
|
||||
public function andReturn(...$args)
|
||||
{
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
return $this->__call(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +89,7 @@ class CompositeExpectation implements ExpectationInterface
|
||||
/**
|
||||
* Return the parent mock of the first expectation
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @return \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
public function getMock()
|
||||
{
|
||||
@@ -91,7 +101,7 @@ class CompositeExpectation implements ExpectationInterface
|
||||
/**
|
||||
* Mockery API alias to getMock
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
|
||||
*/
|
||||
public function mock()
|
||||
{
|
||||
@@ -102,17 +112,30 @@ class CompositeExpectation implements ExpectationInterface
|
||||
* Starts a new expectation addition on the first mock which is the primary
|
||||
* target outside of a demeter chain
|
||||
*
|
||||
* @param mixed ...
|
||||
* @param mixed ...$args
|
||||
* @return \Mockery\Expectation
|
||||
*/
|
||||
public function shouldReceive()
|
||||
public function shouldReceive(...$args)
|
||||
{
|
||||
$args = func_get_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
|
||||
*/
|
||||
public function shouldNotReceive(...$args)
|
||||
{
|
||||
reset($this->_expectations);
|
||||
$first = current($this->_expectations);
|
||||
return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string summary of this composite expectation
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Mockery;
|
||||
|
||||
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)
|
||||
@@ -41,6 +40,11 @@ class Configuration
|
||||
*/
|
||||
protected $_allowMockingMethodsUnnecessarily = true;
|
||||
|
||||
/**
|
||||
* @var QuickDefinitionsConfiguration
|
||||
*/
|
||||
protected $_quickDefinitionsConfiguration;
|
||||
|
||||
/**
|
||||
* Parameter map for use with PHP internal classes.
|
||||
*
|
||||
@@ -48,10 +52,39 @@ class Configuration
|
||||
*/
|
||||
protected $_internalClassParamMap = array();
|
||||
|
||||
protected $_constantsMap = array();
|
||||
|
||||
/**
|
||||
* Boolean assertion is reflection caching enabled or not. It should be
|
||||
* always enabled, except when using PHPUnit's --static-backup option.
|
||||
*
|
||||
* @see https://github.com/mockery/mockery/issues/268
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @param bool
|
||||
* @param bool $flag
|
||||
*/
|
||||
public function allowMockingNonExistentMethods($flag = true)
|
||||
{
|
||||
@@ -71,10 +104,14 @@ class Configuration
|
||||
/**
|
||||
* Set boolean to allow/prevent unnecessary mocking of methods
|
||||
*
|
||||
* @param bool
|
||||
* @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);
|
||||
|
||||
$this->_allowMockingMethodsUnnecessarily = (bool) $flag;
|
||||
}
|
||||
|
||||
@@ -82,9 +119,13 @@ 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);
|
||||
|
||||
return $this->_allowMockingMethodsUnnecessarily;
|
||||
}
|
||||
|
||||
@@ -98,6 +139,10 @@ class Configuration
|
||||
*/
|
||||
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();
|
||||
}
|
||||
@@ -105,7 +150,7 @@ class Configuration
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all overriden parameter maps from internal PHP classes.
|
||||
* Remove all overridden parameter maps from internal PHP classes.
|
||||
*/
|
||||
public function resetInternalClassMethodParamMaps()
|
||||
{
|
||||
@@ -115,7 +160,7 @@ class Configuration
|
||||
/**
|
||||
* Get the parameter map of an internal PHP class method
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
public function getInternalClassMethodParamMap($class, $method)
|
||||
{
|
||||
@@ -128,4 +173,111 @@ class Configuration
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable reflection caching
|
||||
*
|
||||
* It should be always enabled, except when using
|
||||
* PHPUnit's --static-backup option.
|
||||
*
|
||||
* @see https://github.com/mockery/mockery/issues/268
|
||||
*/
|
||||
public function disableReflectionCache()
|
||||
{
|
||||
$this->_reflectionCacheEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable reflection caching
|
||||
*
|
||||
* It should be always enabled, except when using
|
||||
* PHPUnit's --static-backup option.
|
||||
*
|
||||
* @see https://github.com/mockery/mockery/issues/268
|
||||
*/
|
||||
public function enableReflectionCache()
|
||||
{
|
||||
$this->_reflectionCacheEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is reflection cache enabled?
|
||||
*/
|
||||
public function reflectionCacheEnabled()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
227
vendor/mockery/mockery/library/Mockery/Container.php
vendored
227
vendor/mockery/mockery/library/Mockery/Container.php
vendored
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -57,7 +57,7 @@ class Container
|
||||
protected $_groups = array();
|
||||
|
||||
/**
|
||||
* @var Generator\Generator
|
||||
* @var Generator
|
||||
*/
|
||||
protected $_generator;
|
||||
|
||||
@@ -85,17 +85,18 @@ 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
|
||||
*
|
||||
* @return Mock
|
||||
* @throws Exception\RuntimeException
|
||||
* @throws Exception
|
||||
* @return \Mockery\Mock
|
||||
*/
|
||||
public function mock()
|
||||
public function mock(...$args)
|
||||
{
|
||||
$expectationClosure = null;
|
||||
$quickdefs = array();
|
||||
$constructorArgs = null;
|
||||
$blocks = array();
|
||||
$args = func_get_args();
|
||||
$class = null;
|
||||
|
||||
if (count($args) > 1) {
|
||||
$finalArg = end($args);
|
||||
@@ -116,87 +117,83 @@ class Container
|
||||
reset($args);
|
||||
|
||||
$builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps());
|
||||
$builder->setConstantsMap(\Mockery::getConfiguration()->getConstantsMap());
|
||||
|
||||
while (count($args) > 0) {
|
||||
$arg = current($args);
|
||||
$arg = array_shift($args);
|
||||
// check for multiple interfaces
|
||||
if (is_string($arg) && strpos($arg, ',') && !strpos($arg, ']')) {
|
||||
$interfaces = explode(',', str_replace(' ', '', $arg));
|
||||
foreach ($interfaces as $i) {
|
||||
if (!interface_exists($i, true) && !class_exists($i, true)) {
|
||||
throw new \Mockery\Exception(
|
||||
'Class name follows the format for defining multiple'
|
||||
. ' interfaces, however one or more of the interfaces'
|
||||
. ' do not exist or are not included, or the base class'
|
||||
. ' (which you may omit from the mock definition) does not exist'
|
||||
);
|
||||
if (is_string($arg)) {
|
||||
foreach (explode('|', $arg) as $type) {
|
||||
if ($arg === 'null') {
|
||||
// skip PHP 8 'null's
|
||||
} elseif (strpos($type, ',') && !strpos($type, ']')) {
|
||||
$interfaces = explode(',', str_replace(' ', '', $type));
|
||||
$builder->addTargets($interfaces);
|
||||
} elseif (substr($type, 0, 6) == 'alias:') {
|
||||
$type = str_replace('alias:', '', $type);
|
||||
$builder->addTarget('stdClass');
|
||||
$builder->setName($type);
|
||||
} elseif (substr($type, 0, 9) == 'overload:') {
|
||||
$type = str_replace('overload:', '', $type);
|
||||
$builder->setInstanceMock(true);
|
||||
$builder->addTarget('stdClass');
|
||||
$builder->setName($type);
|
||||
} elseif (substr($type, strlen($type)-1, 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], ']'))));
|
||||
$builder->addTarget($class);
|
||||
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);
|
||||
}
|
||||
break; // unions are "sum" types and not "intersections", and so we must only process the first part
|
||||
}
|
||||
$builder->addTargets($interfaces);
|
||||
array_shift($args);
|
||||
|
||||
continue;
|
||||
} elseif (is_string($arg) && substr($arg, 0, 6) == 'alias:') {
|
||||
$name = array_shift($args);
|
||||
$name = str_replace('alias:', '', $name);
|
||||
$builder->addTarget('stdClass');
|
||||
$builder->setName($name);
|
||||
continue;
|
||||
} elseif (is_string($arg) && substr($arg, 0, 9) == 'overload:') {
|
||||
$name = array_shift($args);
|
||||
$name = str_replace('overload:', '', $name);
|
||||
$builder->setInstanceMock(true);
|
||||
$builder->addTarget('stdClass');
|
||||
$builder->setName($name);
|
||||
continue;
|
||||
} elseif (is_string($arg) && substr($arg, strlen($arg)-1, 1) == ']') {
|
||||
$parts = explode('[', $arg);
|
||||
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 = explode(',', strtolower(rtrim($parts[1], ']')));
|
||||
$builder->addTarget($class);
|
||||
$builder->setWhiteListedMethods($partialMethods);
|
||||
array_shift($args);
|
||||
continue;
|
||||
} elseif (is_string($arg) && (class_exists($arg, true) || interface_exists($arg, true))) {
|
||||
$class = array_shift($args);
|
||||
$builder->addTarget($class);
|
||||
continue;
|
||||
} elseif (is_string($arg)) {
|
||||
$class = array_shift($args);
|
||||
$builder->addTarget($class);
|
||||
continue;
|
||||
} elseif (is_object($arg)) {
|
||||
$partial = array_shift($args);
|
||||
$builder->addTarget($partial);
|
||||
continue;
|
||||
} elseif (is_array($arg) && !empty($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 = array_shift($args);
|
||||
continue;
|
||||
$builder->addTarget($arg);
|
||||
} elseif (is_array($arg)) {
|
||||
$constructorArgs = array_shift($args);
|
||||
continue;
|
||||
if (!empty($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;
|
||||
}
|
||||
} else {
|
||||
throw new \Mockery\Exception(
|
||||
'Unable to parse arguments sent to '
|
||||
. get_class($this) . '::mock()'
|
||||
);
|
||||
}
|
||||
|
||||
throw new \Mockery\Exception(
|
||||
'Unable to parse arguments sent to '
|
||||
. get_class($this) . '::mock()'
|
||||
);
|
||||
}
|
||||
|
||||
$builder->addBlackListedMethods($blocks);
|
||||
|
||||
if (!is_null($constructorArgs)) {
|
||||
$builder->addBlackListedMethod("__construct"); // we need to pass through
|
||||
} else {
|
||||
$builder->setMockOriginalDestructor(true);
|
||||
}
|
||||
|
||||
if (!empty($partialMethods) && $constructorArgs === null) {
|
||||
@@ -211,7 +208,7 @@ class Container
|
||||
|
||||
if (class_exists($def->getClassName(), $attemptAutoload = false)) {
|
||||
$rfc = new \ReflectionClass($def->getClassName());
|
||||
if (!$rfc->implementsInterface("Mockery\MockInterface")) {
|
||||
if (!$rfc->implementsInterface("Mockery\LegacyMockInterface")) {
|
||||
throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists");
|
||||
}
|
||||
}
|
||||
@@ -219,10 +216,14 @@ class Container
|
||||
$this->getLoader()->load($def);
|
||||
|
||||
$mock = $this->_getInstance($def->getClassName(), $constructorArgs);
|
||||
$mock->mockery_init($this, $config->getTargetObject());
|
||||
$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);
|
||||
@@ -247,12 +248,13 @@ class Container
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $parent
|
||||
* @return string|null
|
||||
*/
|
||||
public function getKeyOfDemeterMockFor($method)
|
||||
public function getKeyOfDemeterMockFor($method, $parent)
|
||||
{
|
||||
$keys = array_keys($this->_mocks);
|
||||
$match = preg_grep("/__demeter_{$method}$/", $keys);
|
||||
$match = preg_grep("/__demeter_" . md5($parent) . "_{$method}$/", $keys);
|
||||
if (count($match) == 1) {
|
||||
$res = array_values($match);
|
||||
if (count($res) > 0) {
|
||||
@@ -298,6 +300,22 @@ class Container
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the container to its original state
|
||||
*
|
||||
@@ -373,7 +391,7 @@ class Container
|
||||
* @throws \Mockery\Exception
|
||||
* @return void
|
||||
*/
|
||||
public function mockery_validateOrder($method, $order, \Mockery\MockInterface $mock)
|
||||
public function mockery_validateOrder($method, $order, \Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
if ($order < $this->_currentOrder) {
|
||||
$exception = new \Mockery\Exception\InvalidOrderException(
|
||||
@@ -406,10 +424,10 @@ class Container
|
||||
/**
|
||||
* Store a mock and set its container reference
|
||||
*
|
||||
* @param \Mockery\Mock
|
||||
* @return \Mockery\Mock
|
||||
* @param \Mockery\Mock $mock
|
||||
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
|
||||
*/
|
||||
public function rememberMock(\Mockery\MockInterface $mock)
|
||||
public function rememberMock(\Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
if (!isset($this->_mocks[get_class($mock)])) {
|
||||
$this->_mocks[get_class($mock)] = $mock;
|
||||
@@ -459,7 +477,7 @@ class Container
|
||||
}
|
||||
|
||||
try {
|
||||
$instantiator = new Instantiator;
|
||||
$instantiator = new Instantiator();
|
||||
$instance = $instantiator->instantiate($mockName);
|
||||
} catch (\Exception $ex) {
|
||||
$internalMockName = $mockName . '_Internal';
|
||||
@@ -476,31 +494,6 @@ class Container
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a class name and declares it
|
||||
*
|
||||
* @param string $fqcn
|
||||
*/
|
||||
public function declareClass($fqcn)
|
||||
{
|
||||
if (false !== strpos($fqcn, '/')) {
|
||||
throw new \Mockery\Exception(
|
||||
'Class name contains a forward slash instead of backslash needed '
|
||||
. 'when employing namespaces'
|
||||
);
|
||||
}
|
||||
if (false !== strpos($fqcn, "\\")) {
|
||||
$parts = array_filter(explode("\\", $fqcn), function ($part) {
|
||||
return $part !== "";
|
||||
});
|
||||
$cl = array_pop($parts);
|
||||
$ns = implode("\\", $parts);
|
||||
eval(" namespace $ns { class $cl {} }");
|
||||
} else {
|
||||
eval(" class $fqcn {} ");
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkForNamedMockClashes($config)
|
||||
{
|
||||
$name = $config->getName();
|
||||
@@ -521,4 +514,22 @@ class Container
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ use Mockery;
|
||||
|
||||
class AtLeast extends CountValidatorAbstract
|
||||
{
|
||||
|
||||
/**
|
||||
* Checks if the validator can accept an additional nth call
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ use Mockery;
|
||||
|
||||
class AtMost extends CountValidatorAbstract
|
||||
{
|
||||
|
||||
/**
|
||||
* Validate the call count against this validator
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Mockery\CountValidator;
|
||||
|
||||
abstract class CountValidatorAbstract
|
||||
{
|
||||
|
||||
/**
|
||||
* Expectation for which this validator is assigned
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ use Mockery;
|
||||
|
||||
class Exact extends CountValidatorAbstract
|
||||
{
|
||||
|
||||
/**
|
||||
* Validate the call count against this validator
|
||||
*
|
||||
@@ -34,12 +33,15 @@ class Exact extends CountValidatorAbstract
|
||||
public function validate($n)
|
||||
{
|
||||
if ($this->_limit !== $n) {
|
||||
$because = $this->_expectation->getExceptionMessage();
|
||||
|
||||
$exception = new Mockery\Exception\InvalidCountException(
|
||||
'Method ' . (string) $this->_expectation
|
||||
. ' from ' . $this->_expectation->getMock()->mockery_getName()
|
||||
. ' should be called' . PHP_EOL
|
||||
. ' exactly ' . $this->_limit . ' times but called ' . $n
|
||||
. ' times.'
|
||||
. ($because ? ' Because ' . $this->_expectation->getExceptionMessage() : '')
|
||||
);
|
||||
$exception->setMock($this->_expectation->getMock())
|
||||
->setMethodName((string) $this->_expectation)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
|
||||
23
vendor/mockery/mockery/library/Mockery/Exception/BadMethodCallException.php
vendored
Normal file
23
vendor/mockery/mockery/library/Mockery/Exception/BadMethodCallException.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Mockery\Exception;
|
||||
|
||||
class BadMethodCallException extends \BadMethodCallException
|
||||
{
|
||||
private $dismissed = false;
|
||||
|
||||
public function dismiss()
|
||||
{
|
||||
$this->dismissed = true;
|
||||
|
||||
// we sometimes stack them
|
||||
if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) {
|
||||
$this->getPrevious()->dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public function dismissed()
|
||||
{
|
||||
return $this->dismissed;
|
||||
}
|
||||
}
|
||||
@@ -7,21 +7,19 @@
|
||||
* 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/master/LICENSE
|
||||
* 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
|
||||
* @subpackage UnitTests
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
namespace test\Mockery\Fixtures;
|
||||
namespace Mockery\Exception;
|
||||
|
||||
interface VoidMethod
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
public function foo(): void;
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ use Mockery\Exception\RuntimeException;
|
||||
|
||||
class InvalidCountException extends Mockery\CountValidator\Exception
|
||||
{
|
||||
|
||||
protected $method = null;
|
||||
|
||||
protected $expected = 0;
|
||||
@@ -36,7 +35,7 @@ class InvalidCountException extends Mockery\CountValidator\Exception
|
||||
|
||||
protected $mockObject = null;
|
||||
|
||||
public function setMock(Mockery\MockInterface $mock)
|
||||
public function setMock(Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
$this->mockObject = $mock;
|
||||
return $this;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ use Mockery;
|
||||
|
||||
class InvalidOrderException extends Mockery\Exception
|
||||
{
|
||||
|
||||
protected $method = null;
|
||||
|
||||
protected $expected = 0;
|
||||
@@ -33,7 +32,7 @@ class InvalidOrderException extends Mockery\Exception
|
||||
|
||||
protected $mockObject = null;
|
||||
|
||||
public function setMock(Mockery\MockInterface $mock)
|
||||
public function setMock(Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
$this->mockObject = $mock;
|
||||
return $this;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -24,14 +24,13 @@ use Mockery;
|
||||
|
||||
class NoMatchingExpectationException extends Mockery\Exception
|
||||
{
|
||||
|
||||
protected $method = null;
|
||||
|
||||
protected $actual = array();
|
||||
|
||||
protected $mockObject = null;
|
||||
|
||||
public function setMock(Mockery\MockInterface $mock)
|
||||
public function setMock(Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
$this->mockObject = $mock;
|
||||
return $this;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
|
||||
@@ -14,19 +14,25 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @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;
|
||||
|
||||
use Closure;
|
||||
use Mockery\Matcher\NoArgs;
|
||||
use Mockery\Matcher\AnyArgs;
|
||||
use Mockery\Matcher\AndAnyOtherArgs;
|
||||
use Mockery\Matcher\ArgumentListMatcher;
|
||||
use Mockery\Matcher\MultiArgumentClosure;
|
||||
|
||||
class Expectation implements ExpectationInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Mock object to which this expectation belongs
|
||||
*
|
||||
* @var object
|
||||
* @var \Mockery\LegacyMockInterface
|
||||
*/
|
||||
protected $_mock = null;
|
||||
|
||||
@@ -37,6 +43,13 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
protected $_name = null;
|
||||
|
||||
/**
|
||||
* Exception message
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $_because = null;
|
||||
|
||||
/**
|
||||
* Arguments expected by this expectation
|
||||
*
|
||||
@@ -123,13 +136,6 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
protected $_globally = false;
|
||||
|
||||
/**
|
||||
* Flag indicating we expect no arguments
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_noArgsExpectation = false;
|
||||
|
||||
/**
|
||||
* Flag indicating if the return value should be obtained from the original
|
||||
* class method instead of returning predefined values from the return queue
|
||||
@@ -141,13 +147,14 @@ class Expectation implements ExpectationInterface
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Mockery\MockInterface $mock
|
||||
* @param \Mockery\LegacyMockInterface $mock
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(\Mockery\MockInterface $mock, $name)
|
||||
public function __construct(\Mockery\LegacyMockInterface $mock, $name)
|
||||
{
|
||||
$this->_mock = $mock;
|
||||
$this->_name = $name;
|
||||
$this->withAnyArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,12 +183,31 @@ class Expectation implements ExpectationInterface
|
||||
if (true === $this->_passthru) {
|
||||
return $this->_mock->mockery_callSubjectMethod($this->_name, $args);
|
||||
}
|
||||
|
||||
$return = $this->_getReturnValue($args);
|
||||
if ($return instanceof \Exception && $this->_throw === true) {
|
||||
$this->throwAsNecessary($return);
|
||||
$this->_setValues();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the expectation has been configured to do so
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @return void
|
||||
*/
|
||||
private function throwAsNecessary($return)
|
||||
{
|
||||
if (!$this->_throw) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($return instanceof \Throwable) {
|
||||
throw $return;
|
||||
}
|
||||
$this->_setValues();
|
||||
return $return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,10 +218,19 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
protected function _setValues()
|
||||
{
|
||||
$mockClass = get_class($this->_mock);
|
||||
$container = $this->_mock->mockery_getContainer();
|
||||
/** @var Mock[] $mocks */
|
||||
$mocks = $container->getMocks();
|
||||
foreach ($this->_setQueue as $name => &$values) {
|
||||
if (count($values) > 0) {
|
||||
$value = array_shift($values);
|
||||
$this->_mock->{$name} = $value;
|
||||
foreach ($mocks as $mock) {
|
||||
if (is_a($mock, $mockClass) && $mock->mockery_isInstance()) {
|
||||
$mock->{$name} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,32 +253,7 @@ class Expectation implements ExpectationInterface
|
||||
return current($this->_returnQueue);
|
||||
}
|
||||
|
||||
$rm = $this->_mock->mockery_getMethod($this->_name);
|
||||
if ($rm && version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $rm->hasReturnType()) {
|
||||
$type = (string) $rm->getReturnType();
|
||||
switch ($type) {
|
||||
case '': return;
|
||||
case 'void': return;
|
||||
case 'string': return '';
|
||||
case 'int': return 0;
|
||||
case 'float': return 0.0;
|
||||
case 'bool': return false;
|
||||
case 'array': return array();
|
||||
|
||||
case 'callable':
|
||||
case 'Closure':
|
||||
return function () {};
|
||||
|
||||
case 'Traversable':
|
||||
case 'Generator':
|
||||
// Remove eval() when minimum version >=5.5
|
||||
$generator = eval('return function () { yield; };');
|
||||
return $generator();
|
||||
|
||||
default:
|
||||
return \Mockery::mock($type);
|
||||
}
|
||||
}
|
||||
return $this->_mock->mockery_returnValueForMethod($this->_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +300,7 @@ class Expectation implements ExpectationInterface
|
||||
/**
|
||||
* Verify this expectation
|
||||
*
|
||||
* @return bool
|
||||
* @return void
|
||||
*/
|
||||
public function verify()
|
||||
{
|
||||
@@ -299,6 +309,20 @@ class Expectation implements ExpectationInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the registered expectation is an ArgumentListMatcher
|
||||
* @return bool
|
||||
*/
|
||||
private function isArgumentListMatcher()
|
||||
{
|
||||
return (count($this->_expectedArgs) === 1 && ($this->_expectedArgs[0] instanceof ArgumentListMatcher));
|
||||
}
|
||||
|
||||
private function isAndAnyOtherArgumentsMatcher($expectedArg)
|
||||
{
|
||||
return $expectedArg instanceof AndAnyOtherArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed arguments match an argument expectation
|
||||
*
|
||||
@@ -307,12 +331,33 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
public function matchArgs(array $args)
|
||||
{
|
||||
if (empty($this->_expectedArgs) && !$this->_noArgsExpectation) {
|
||||
return true;
|
||||
if ($this->isArgumentListMatcher()) {
|
||||
return $this->_matchArg($this->_expectedArgs[0], $args);
|
||||
}
|
||||
if (count($args) !== count($this->_expectedArgs)) {
|
||||
$argCount = count($args);
|
||||
if ($argCount !== count((array) $this->_expectedArgs)) {
|
||||
$lastExpectedArgument = end($this->_expectedArgs);
|
||||
reset($this->_expectedArgs);
|
||||
|
||||
if ($this->isAndAnyOtherArgumentsMatcher($lastExpectedArgument)) {
|
||||
$args = array_slice($args, 0, array_search($lastExpectedArgument, $this->_expectedArgs, true));
|
||||
return $this->_matchArgs($args);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->_matchArgs($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed arguments match the expectations, one by one.
|
||||
*
|
||||
* @param array $args
|
||||
* @return bool
|
||||
*/
|
||||
protected function _matchArgs($args)
|
||||
{
|
||||
$argCount = count($args);
|
||||
for ($i=0; $i<$argCount; $i++) {
|
||||
$param =& $args[$i];
|
||||
@@ -320,14 +365,14 @@ class Expectation implements ExpectationInterface
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed argument matches an argument expectation
|
||||
*
|
||||
* @param array $args
|
||||
* @param mixed $expected
|
||||
* @param mixed $actual
|
||||
* @return bool
|
||||
*/
|
||||
protected function _matchArg($expected, &$actual)
|
||||
@@ -338,26 +383,22 @@ class Expectation implements ExpectationInterface
|
||||
if (!is_object($expected) && !is_object($actual) && $expected == $actual) {
|
||||
return true;
|
||||
}
|
||||
if (is_string($expected) && !is_array($actual) && !is_object($actual)) {
|
||||
# push/pop an error handler here to to make sure no error/exception thrown if $expected is not a regex
|
||||
set_error_handler(function () {});
|
||||
$result = preg_match($expected, (string) $actual);
|
||||
restore_error_handler();
|
||||
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_string($expected) && is_object($actual)) {
|
||||
$result = $actual instanceof $expected;
|
||||
if ($result) {
|
||||
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);
|
||||
}
|
||||
if (is_a($expected, '\Hamcrest\Matcher') || is_a($expected, '\Hamcrest_Matcher')) {
|
||||
if ($expected instanceof \Hamcrest\Matcher || $expected instanceof \Hamcrest_Matcher) {
|
||||
return $expected->matches($actual);
|
||||
}
|
||||
return false;
|
||||
@@ -366,27 +407,59 @@ class Expectation implements ExpectationInterface
|
||||
/**
|
||||
* Expected argument setter for the expectation
|
||||
*
|
||||
* @param mixed ...
|
||||
* @param mixed ...$args
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function with()
|
||||
public function with(...$args)
|
||||
{
|
||||
return $this->withArgs(func_get_args());
|
||||
return $this->withArgs($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected arguments for the expectation passed as an array
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $arguments
|
||||
* @return self
|
||||
*/
|
||||
public function withArgs(array $args)
|
||||
private function withArgsInArray(array $arguments)
|
||||
{
|
||||
if (empty($args)) {
|
||||
if (empty($arguments)) {
|
||||
return $this->withNoArgs();
|
||||
}
|
||||
$this->_expectedArgs = $args;
|
||||
$this->_noArgsExpectation = false;
|
||||
$this->_expectedArgs = $arguments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected arguments have to be matched by the given closure.
|
||||
*
|
||||
* @param Closure $closure
|
||||
* @return self
|
||||
*/
|
||||
private function withArgsMatchedByClosure(Closure $closure)
|
||||
{
|
||||
$this->_expectedArgs = [new MultiArgumentClosure($closure)];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected arguments for the expectation passed as an array or a closure that matches each passed argument on
|
||||
* each function call.
|
||||
*
|
||||
* @param array|Closure $argsOrClosure
|
||||
* @return self
|
||||
*/
|
||||
public function withArgs($argsOrClosure)
|
||||
{
|
||||
if (is_array($argsOrClosure)) {
|
||||
$this->withArgsInArray($argsOrClosure);
|
||||
} elseif ($argsOrClosure instanceof Closure) {
|
||||
$this->withArgsMatchedByClosure($argsOrClosure);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Call to %s with an invalid argument (%s), only array and ' .
|
||||
'closure are allowed', __METHOD__, $argsOrClosure));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -397,8 +470,7 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
public function withNoArgs()
|
||||
{
|
||||
$this->_noArgsExpectation = true;
|
||||
$this->_expectedArgs = null;
|
||||
$this->_expectedArgs = [new NoArgs()];
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -409,20 +481,49 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
public function withAnyArgs()
|
||||
{
|
||||
$this->_expectedArgs = array();
|
||||
$this->_expectedArgs = [new AnyArgs()];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected arguments should partially match the real arguments
|
||||
*
|
||||
* @param mixed ...$expectedArgs
|
||||
* @return self
|
||||
*/
|
||||
public function withSomeOfArgs(...$expectedArgs)
|
||||
{
|
||||
return $this->withArgs(function (...$args) use ($expectedArgs) {
|
||||
foreach ($expectedArgs as $expectedArg) {
|
||||
if (!in_array($expectedArg, $args, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a return value, or sequential queue of return values
|
||||
*
|
||||
* @param mixed ...$args
|
||||
* @return self
|
||||
*/
|
||||
public function andReturn(...$args)
|
||||
{
|
||||
$this->_returnQueue = $args;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a return value, or sequential queue of return values
|
||||
*
|
||||
* @param mixed ...
|
||||
* @param mixed ...$args
|
||||
* @return self
|
||||
*/
|
||||
public function andReturn()
|
||||
public function andReturns(...$args)
|
||||
{
|
||||
$this->_returnQueue = func_get_args();
|
||||
return $this;
|
||||
return call_user_func_array([$this, 'andReturn'], $args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,12 +553,34 @@ class Expectation implements ExpectationInterface
|
||||
* values. The arguments passed to the expected method are passed to the
|
||||
* closures as parameters.
|
||||
*
|
||||
* @param callable ...
|
||||
* @param callable ...$args
|
||||
* @return self
|
||||
*/
|
||||
public function andReturnUsing()
|
||||
public function andReturnUsing(...$args)
|
||||
{
|
||||
$this->_closureQueue = func_get_args();
|
||||
$this->_closureQueue = $args;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a closure to return the nth argument from the expected method call
|
||||
*
|
||||
* @param int $index
|
||||
* @return self
|
||||
*/
|
||||
public function andReturnArg($index)
|
||||
{
|
||||
if (!is_int($index) || $index < 0) {
|
||||
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)) {
|
||||
return $args[$index];
|
||||
}
|
||||
throw new \OutOfBoundsException("Cannot return an argument value. No argument exists for the index $index");
|
||||
};
|
||||
|
||||
$this->_closureQueue = [$closure];
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -468,7 +591,7 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
public function andReturnUndefined()
|
||||
{
|
||||
$this->andReturn(new \Mockery\Undefined);
|
||||
$this->andReturn(new \Mockery\Undefined());
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -479,16 +602,26 @@ class Expectation implements ExpectationInterface
|
||||
*/
|
||||
public function andReturnNull()
|
||||
{
|
||||
return $this;
|
||||
return $this->andReturn(null);
|
||||
}
|
||||
|
||||
public function andReturnFalse()
|
||||
{
|
||||
return $this->andReturn(false);
|
||||
}
|
||||
|
||||
public function andReturnTrue()
|
||||
{
|
||||
return $this->andReturn(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Exception class and arguments to that class to be thrown
|
||||
*
|
||||
* @param string $exception
|
||||
* @param string|\Exception $exception
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Exception $previous
|
||||
* @param \Exception $previous
|
||||
* @return self
|
||||
*/
|
||||
public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
|
||||
@@ -502,6 +635,11 @@ class Expectation implements ExpectationInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function andThrows($exception, $message = '', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
return $this->andThrow($exception, $message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Exception classes to be thrown
|
||||
*
|
||||
@@ -523,17 +661,34 @@ class Expectation implements ExpectationInterface
|
||||
* Register values to be set to a public property each time this expectation occurs
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param array ...$values
|
||||
* @return self
|
||||
*/
|
||||
public function andSet($name, $value)
|
||||
public function andSet($name, ...$values)
|
||||
{
|
||||
$values = func_get_args();
|
||||
array_shift($values);
|
||||
$this->_setQueue[$name] = $values;
|
||||
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')
|
||||
@@ -561,6 +716,7 @@ class Expectation implements ExpectationInterface
|
||||
* Indicates the number of times this expectation should occur
|
||||
*
|
||||
* @param int $limit
|
||||
* @throws \InvalidArgumentException
|
||||
* @return self
|
||||
*/
|
||||
public function times($limit = null)
|
||||
@@ -568,8 +724,16 @@ class Expectation implements ExpectationInterface
|
||||
if (is_null($limit)) {
|
||||
return $this;
|
||||
}
|
||||
$this->_countValidators[] = new $this->_countValidatorClass($this, $limit);
|
||||
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
|
||||
if (!is_int($limit)) {
|
||||
throw new \InvalidArgumentException('The passed Times limit should be an integer value');
|
||||
}
|
||||
$this->_countValidators[$this->_countValidatorClass] = new $this->_countValidatorClass($this, $limit);
|
||||
|
||||
if ('Mockery\CountValidator\Exact' !== $this->_countValidatorClass) {
|
||||
$this->_countValidatorClass = 'Mockery\CountValidator\Exact';
|
||||
unset($this->_countValidators[$this->_countValidatorClass]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -636,6 +800,19 @@ class Expectation implements ExpectationInterface
|
||||
return $this->atLeast()->times($minimum)->atMost()->times($maximum);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the exception message
|
||||
*
|
||||
* @param string $message
|
||||
* @return $this
|
||||
*/
|
||||
public function because($message)
|
||||
{
|
||||
$this->_because = $message;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this expectation must be called in a specific given order
|
||||
*
|
||||
@@ -712,7 +889,7 @@ class Expectation implements ExpectationInterface
|
||||
/**
|
||||
* Return the parent mock of the expectation
|
||||
*
|
||||
* @return \Mockery\MockInterface
|
||||
* @return \Mockery\LegacyMockInterface|\Mockery\MockInterface
|
||||
*/
|
||||
public function getMock()
|
||||
{
|
||||
@@ -755,4 +932,9 @@ class Expectation implements ExpectationInterface
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
public function getExceptionMessage()
|
||||
{
|
||||
return $this->_because;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Mockery;
|
||||
|
||||
class ExpectationDirector
|
||||
{
|
||||
|
||||
/**
|
||||
* Method name the director is directing
|
||||
*
|
||||
@@ -33,7 +32,7 @@ class ExpectationDirector
|
||||
/**
|
||||
* Mock object the director is attached to
|
||||
*
|
||||
* @var \Mockery\MockInterface
|
||||
* @var \Mockery\MockInterface|\Mockery\LegacyMockInterface
|
||||
*/
|
||||
protected $_mock = null;
|
||||
|
||||
@@ -62,9 +61,9 @@ class ExpectationDirector
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Mockery\MockInterface $mock
|
||||
* @param \Mockery\LegacyMockInterface $mock
|
||||
*/
|
||||
public function __construct($name, \Mockery\MockInterface $mock)
|
||||
public function __construct($name, \Mockery\LegacyMockInterface $mock)
|
||||
{
|
||||
$this->_name = $name;
|
||||
$this->_mock = $mock;
|
||||
@@ -73,7 +72,7 @@ class ExpectationDirector
|
||||
/**
|
||||
* Add a new expectation to the director
|
||||
*
|
||||
* @param Mutateme\Expectation $expectation
|
||||
* @param \Mockery\Expectation $expectation
|
||||
*/
|
||||
public function addExpectation(\Mockery\Expectation $expectation)
|
||||
{
|
||||
@@ -134,18 +133,24 @@ class ExpectationDirector
|
||||
*/
|
||||
public function findExpectation(array $args)
|
||||
{
|
||||
$expectation = null;
|
||||
|
||||
if (!empty($this->_expectations)) {
|
||||
return $this->_findExpectationIn($this->_expectations, $args);
|
||||
} else {
|
||||
return $this->_findExpectationIn($this->_defaults, $args);
|
||||
$expectation = $this->_findExpectationIn($this->_expectations, $args);
|
||||
}
|
||||
|
||||
if ($expectation === null && !empty($this->_defaults)) {
|
||||
$expectation = $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
|
||||
* @param \Mockery\Expectation $expectation
|
||||
*/
|
||||
public function makeExpectationDefault(\Mockery\Expectation $expectation)
|
||||
{
|
||||
@@ -170,7 +175,7 @@ class ExpectationDirector
|
||||
protected function _findExpectationIn(array $expectations, array $args)
|
||||
{
|
||||
foreach ($expectations as $exp) {
|
||||
if ($exp->matchArgs($args) && $exp->isEligible()) {
|
||||
if ($exp->isEligible() && $exp->matchArgs($args)) {
|
||||
return $exp;
|
||||
}
|
||||
}
|
||||
@@ -191,6 +196,16 @@ class ExpectationDirector
|
||||
return $this->_expectations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all expectations assigned to this director
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultExpectations()
|
||||
{
|
||||
return $this->_defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of expectations assigned to this director.
|
||||
*
|
||||
@@ -198,6 +213,14 @@ class ExpectationDirector
|
||||
*/
|
||||
public function getExpectationCount()
|
||||
{
|
||||
return count($this->getExpectations());
|
||||
$count = 0;
|
||||
/** @var Expectation $expectations */
|
||||
$expectations = $this->getExpectations() ?: $this->getDefaultExpectations();
|
||||
foreach ($expectations as $expectation) {
|
||||
if ($expectation->isCallCountConstrained()) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*
|
||||
* @category Mockery
|
||||
* @package Mockery
|
||||
* @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @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;
|
||||
|
||||
interface ExpectationInterface
|
||||
@@ -28,12 +29,18 @@ interface ExpectationInterface
|
||||
public function getOrderNumber();
|
||||
|
||||
/**
|
||||
* @return MockInterface
|
||||
* @return LegacyMockInterface|MockInterface
|
||||
*/
|
||||
public function getMock();
|
||||
|
||||
/**
|
||||
* @param mixed $args
|
||||
* @return self
|
||||
*/
|
||||
public function andReturn();
|
||||
public function andReturn(...$args);
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function andReturns();
|
||||
}
|
||||
|
||||
38
vendor/mockery/mockery/library/Mockery/ExpectsHigherOrderMessage.php
vendored
Normal file
38
vendor/mockery/mockery/library/Mockery/ExpectsHigherOrderMessage.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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 ExpectsHigherOrderMessage extends HigherOrderMessage
|
||||
{
|
||||
public function __construct(MockInterface $mock)
|
||||
{
|
||||
parent::__construct($mock, "shouldReceive");
|
||||
}
|
||||
/**
|
||||
* @return \Mockery\Expectation
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
$expectation = parent::__call($method, $args);
|
||||
|
||||
return $expectation->once();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator;
|
||||
|
||||
|
||||
@@ -1,24 +1,44 @@
|
||||
<?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\Generator;
|
||||
|
||||
class DefinedTargetClass
|
||||
class DefinedTargetClass implements TargetClassInterface
|
||||
{
|
||||
private $rfc;
|
||||
private $name;
|
||||
|
||||
public function __construct(\ReflectionClass $rfc)
|
||||
public function __construct(\ReflectionClass $rfc, $alias = null)
|
||||
{
|
||||
$this->rfc = $rfc;
|
||||
$this->name = $alias === null ? $rfc->getName() : $alias;
|
||||
}
|
||||
|
||||
public static function factory($name)
|
||||
public static function factory($name, $alias = null)
|
||||
{
|
||||
return new self(new \ReflectionClass($name));
|
||||
return new self(new \ReflectionClass($name), $alias);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->rfc->getName();
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function isAbstract()
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator;
|
||||
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
<?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\Generator;
|
||||
|
||||
use Mockery\Reflector;
|
||||
|
||||
class Method
|
||||
{
|
||||
/** @var \ReflectionMethod */
|
||||
private $method;
|
||||
|
||||
public function __construct(\ReflectionMethod $method)
|
||||
@@ -16,28 +37,21 @@ class Method
|
||||
return call_user_func_array(array($this->method, $method), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Parameter[]
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return array_map(function ($parameter) {
|
||||
return array_map(function (\ReflectionParameter $parameter) {
|
||||
return new Parameter($parameter);
|
||||
}, $this->method->getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getReturnType()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $this->method->hasReturnType()) {
|
||||
$returnType = (string) $this->method->getReturnType();
|
||||
|
||||
if ('self' === $returnType) {
|
||||
$returnType = "\\".$this->method->getDeclaringClass()->getName();
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.1.0-dev') >= 0 && $this->method->getReturnType()->allowsNull()) {
|
||||
$returnType = '?'.$returnType;
|
||||
}
|
||||
|
||||
return $returnType;
|
||||
}
|
||||
return '';
|
||||
return Reflector::getReturnType($this->method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator;
|
||||
|
||||
@@ -8,8 +26,6 @@ namespace Mockery\Generator;
|
||||
*/
|
||||
class MockConfiguration
|
||||
{
|
||||
protected static $mockCounter = 0;
|
||||
|
||||
/**
|
||||
* A class that we'd like to mock
|
||||
*/
|
||||
@@ -23,6 +39,13 @@ class MockConfiguration
|
||||
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
|
||||
*/
|
||||
@@ -62,14 +85,31 @@ class MockConfiguration
|
||||
*/
|
||||
protected $allMethods;
|
||||
|
||||
public function __construct(array $targets = array(), array $blackListedMethods = array(), array $whiteListedMethods = array(), $name = null, $instanceMock = false, array $parameterOverrides = array())
|
||||
{
|
||||
/**
|
||||
* If true, overrides original class destructor
|
||||
*/
|
||||
protected $mockOriginalDestructor = false;
|
||||
|
||||
protected $constantsMap = array();
|
||||
|
||||
public function __construct(
|
||||
array $targets = array(),
|
||||
array $blackListedMethods = array(),
|
||||
array $whiteListedMethods = array(),
|
||||
$name = null,
|
||||
$instanceMock = false,
|
||||
array $parameterOverrides = array(),
|
||||
$mockOriginalDestructor = false,
|
||||
array $constantsMap = array()
|
||||
) {
|
||||
$this->addTargets($targets);
|
||||
$this->blackListedMethods = $blackListedMethods;
|
||||
$this->whiteListedMethods = $whiteListedMethods;
|
||||
$this->name = $name;
|
||||
$this->instanceMock = $instanceMock;
|
||||
$this->parameterOverrides = $parameterOverrides;
|
||||
$this->mockOriginalDestructor = $mockOriginalDestructor;
|
||||
$this->constantsMap = $constantsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,13 +122,15 @@ class MockConfiguration
|
||||
public function getHash()
|
||||
{
|
||||
$vars = array(
|
||||
'targetClassName' => $this->targetClassName,
|
||||
'targetInterfaceNames' => $this->targetInterfaceNames,
|
||||
'name' => $this->name,
|
||||
'blackListedMethods' => $this->blackListedMethods,
|
||||
'whiteListedMethod' => $this->whiteListedMethods,
|
||||
'instanceMock' => $this->instanceMock,
|
||||
'parameterOverrides' => $this->parameterOverrides,
|
||||
'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));
|
||||
@@ -192,6 +234,10 @@ class MockConfiguration
|
||||
$targets = array_merge($targets, $this->targetInterfaceNames);
|
||||
}
|
||||
|
||||
if ($this->targetTraitNames) {
|
||||
$targets = array_merge($targets, $this->targetTraitNames);
|
||||
}
|
||||
|
||||
if ($this->targetObject) {
|
||||
$targets[] = $this->targetObject;
|
||||
}
|
||||
@@ -202,7 +248,9 @@ class MockConfiguration
|
||||
$this->whiteListedMethods,
|
||||
$className,
|
||||
$this->instanceMock,
|
||||
$this->parameterOverrides
|
||||
$this->parameterOverrides,
|
||||
$this->mockOriginalDestructor,
|
||||
$this->constantsMap
|
||||
);
|
||||
}
|
||||
|
||||
@@ -228,6 +276,11 @@ class MockConfiguration
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (trait_exists($target)) {
|
||||
$this->addTargetTraitName($target);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default is to set as class, or interface if class already set
|
||||
*
|
||||
@@ -265,7 +318,15 @@ class MockConfiguration
|
||||
}
|
||||
|
||||
if (class_exists($this->targetClassName)) {
|
||||
$dtc = DefinedTargetClass::factory($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(
|
||||
@@ -279,12 +340,26 @@ class MockConfiguration
|
||||
|
||||
$this->targetClass = $dtc;
|
||||
} else {
|
||||
$this->targetClass = new UndefinedTargetClass($this->targetClassName);
|
||||
$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)) {
|
||||
@@ -293,8 +368,8 @@ class MockConfiguration
|
||||
|
||||
foreach ($this->targetInterfaceNames as $targetInterface) {
|
||||
if (!interface_exists($targetInterface)) {
|
||||
$this->targetInterfaces[] = new UndefinedTargetClass($targetInterface);
|
||||
return;
|
||||
$this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface);
|
||||
continue;
|
||||
}
|
||||
|
||||
$dtc = DefinedTargetClass::factory($targetInterface);
|
||||
@@ -349,24 +424,23 @@ class MockConfiguration
|
||||
*/
|
||||
public function generateName()
|
||||
{
|
||||
$name = 'Mockery_' . static::$mockCounter++;
|
||||
$nameBuilder = new MockNameBuilder();
|
||||
|
||||
if ($this->getTargetObject()) {
|
||||
$name .= "_" . str_replace("\\", "_", get_class($this->getTargetObject()));
|
||||
$className = get_class($this->getTargetObject());
|
||||
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
|
||||
}
|
||||
|
||||
if ($this->getTargetClass()) {
|
||||
$name .= "_" . str_replace("\\", "_", $this->getTargetClass()->getName());
|
||||
$className = $this->getTargetClass()->getName();
|
||||
$nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className);
|
||||
}
|
||||
|
||||
if ($this->getTargetInterfaces()) {
|
||||
$name .= array_reduce($this->getTargetInterfaces(), function ($tmpname, $i) {
|
||||
$tmpname .= '_' . str_replace("\\", "_", $i->getName());
|
||||
return $tmpname;
|
||||
}, '');
|
||||
foreach ($this->getTargetInterfaces() as $targetInterface) {
|
||||
$nameBuilder->addPart($targetInterface->getName());
|
||||
}
|
||||
|
||||
return $name;
|
||||
return $nameBuilder->build();
|
||||
}
|
||||
|
||||
public function getShortName()
|
||||
@@ -407,6 +481,11 @@ class MockConfiguration
|
||||
return $this->parameterOverrides;
|
||||
}
|
||||
|
||||
public function isMockOriginalDestructor()
|
||||
{
|
||||
return $this->mockOriginalDestructor;
|
||||
}
|
||||
|
||||
protected function setTargetClassName($targetClassName)
|
||||
{
|
||||
$this->targetClassName = $targetClassName;
|
||||
@@ -429,6 +508,14 @@ class MockConfiguration
|
||||
$methods = array_merge($methods, $class->getMethods());
|
||||
}
|
||||
|
||||
foreach ($this->getTargetTraits() as $trait) {
|
||||
foreach ($trait->getMethods() as $method) {
|
||||
if ($method->isAbstract()) {
|
||||
$methods[] = $method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$names = array();
|
||||
$methods = array_filter($methods, function ($method) use (&$names) {
|
||||
if (in_array($method->getName(), $names)) {
|
||||
@@ -452,9 +539,18 @@ class MockConfiguration
|
||||
$this->targetInterfaceNames[] = $targetInterface;
|
||||
}
|
||||
|
||||
protected function addTargetTraitName($targetTraitName)
|
||||
{
|
||||
$this->targetTraitNames[] = $targetTraitName;
|
||||
}
|
||||
|
||||
protected function setTargetObject($object)
|
||||
{
|
||||
$this->targetObject = $object;
|
||||
}
|
||||
|
||||
public function getConstantsMap()
|
||||
{
|
||||
return $this->constantsMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator;
|
||||
|
||||
@@ -15,7 +33,7 @@ class MockConfigurationBuilder
|
||||
'__toString',
|
||||
'__isset',
|
||||
'__destruct',
|
||||
'__debugInfo',
|
||||
'__debugInfo', ## mocking this makes it difficult to debug with xdebug
|
||||
|
||||
// below are reserved words in PHP
|
||||
"__halt_compiler", "abstract", "and", "array", "as",
|
||||
@@ -32,12 +50,31 @@ class MockConfigurationBuilder
|
||||
"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",
|
||||
];
|
||||
|
||||
protected $whiteListedMethods = array();
|
||||
protected $instanceMock = false;
|
||||
protected $parameterOverrides = array();
|
||||
|
||||
protected $mockOriginalDestructor = false;
|
||||
protected $targets = array();
|
||||
|
||||
protected $constantsMap = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords);
|
||||
}
|
||||
|
||||
public function addTarget($target)
|
||||
{
|
||||
$this->targets[] = $target;
|
||||
@@ -110,6 +147,17 @@ class MockConfigurationBuilder
|
||||
$this->parameterOverrides = $overrides;
|
||||
}
|
||||
|
||||
public function setMockOriginalDestructor($mockDestructor)
|
||||
{
|
||||
$this->mockOriginalDestructor = $mockDestructor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setConstantsMap(array $map)
|
||||
{
|
||||
$this->constantsMap = $map;
|
||||
}
|
||||
|
||||
public function getMockConfiguration()
|
||||
{
|
||||
return new MockConfiguration(
|
||||
@@ -118,7 +166,9 @@ class MockConfigurationBuilder
|
||||
$this->whiteListedMethods,
|
||||
$this->name,
|
||||
$this->instanceMock,
|
||||
$this->parameterOverrides
|
||||
$this->parameterOverrides,
|
||||
$this->mockOriginalDestructor,
|
||||
$this->constantsMap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator;
|
||||
|
||||
|
||||
@@ -7,43 +7,40 @@
|
||||
* 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/master/LICENSE
|
||||
* 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
|
||||
* @subpackage UnitTests
|
||||
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
|
||||
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
|
||||
*/
|
||||
|
||||
namespace test\Mockery\Fixtures;
|
||||
namespace Mockery\Generator;
|
||||
|
||||
class MethodWithNullableParameters
|
||||
class MockNameBuilder
|
||||
{
|
||||
public function nonNullablePrimitive(string $a)
|
||||
protected static $mockCounter = 0;
|
||||
|
||||
protected $parts = [];
|
||||
|
||||
public function addPart($part)
|
||||
{
|
||||
$this->parts[] = $part;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function nullablePrimitive(?string $a)
|
||||
public function build()
|
||||
{
|
||||
}
|
||||
$parts = ['Mockery', static::$mockCounter++];
|
||||
|
||||
public function nonNullableSelf(self $a)
|
||||
{
|
||||
}
|
||||
foreach ($this->parts as $part) {
|
||||
$parts[] = str_replace("\\", "_", $part);
|
||||
}
|
||||
|
||||
public function nullableSelf(?self $a)
|
||||
{
|
||||
}
|
||||
|
||||
public function nonNullableClass(MethodWithNullableParameters $a)
|
||||
{
|
||||
}
|
||||
|
||||
public function nullableClass(?MethodWithNullableParameters $a)
|
||||
{
|
||||
return implode('_', $parts);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,33 @@
|
||||
<?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\Generator;
|
||||
|
||||
use Mockery\Reflector;
|
||||
|
||||
class Parameter
|
||||
{
|
||||
private static $parameterCounter;
|
||||
/** @var int */
|
||||
private static $parameterCounter = 0;
|
||||
|
||||
/** @var \ReflectionParameter */
|
||||
private $rfp;
|
||||
|
||||
public function __construct(\ReflectionParameter $rfp)
|
||||
@@ -18,84 +40,78 @@ class Parameter
|
||||
return call_user_func_array(array($this->rfp, $method), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reflection class for the parameter type, if it exists.
|
||||
*
|
||||
* This will be null if there was no type, or it was a scalar or a union.
|
||||
*
|
||||
* @return \ReflectionClass|null
|
||||
*
|
||||
* @deprecated since 1.3.3 and will be removed in 2.0.
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return new DefinedTargetClass($this->rfp->getClass());
|
||||
}
|
||||
$typeHint = Reflector::getTypeHint($this->rfp, true);
|
||||
|
||||
public function getTypeHintAsString()
|
||||
{
|
||||
if (method_exists($this->rfp, 'getTypehintText')) {
|
||||
// Available in HHVM
|
||||
$typehint = $this->rfp->getTypehintText();
|
||||
|
||||
// not exhaustive, but will do for now
|
||||
if (in_array($typehint, array('int', 'integer', 'float', 'string', 'bool', 'boolean'))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $typehint;
|
||||
}
|
||||
|
||||
if ($this->rfp->isArray()) {
|
||||
return 'array';
|
||||
}
|
||||
|
||||
/*
|
||||
* PHP < 5.4.1 has some strange behaviour with a typehint of self and
|
||||
* subclass signatures, so we risk the regexp instead
|
||||
*/
|
||||
if ((version_compare(PHP_VERSION, '5.4.1') >= 0)) {
|
||||
try {
|
||||
if ($this->rfp->getClass()) {
|
||||
return $this->getOptionalSign() . $this->rfp->getClass()->getName();
|
||||
}
|
||||
} catch (\ReflectionException $re) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0 && $this->rfp->hasType()) {
|
||||
return $this->getOptionalSign() . $this->rfp->getType();
|
||||
}
|
||||
|
||||
if (preg_match('/^Parameter #[0-9]+ \[ \<(required|optional)\> (?<typehint>\S+ )?.*\$' . $this->rfp->getName() . ' .*\]$/', $this->rfp->__toString(), $typehintMatch)) {
|
||||
if (!empty($typehintMatch['typehint'])) {
|
||||
return $typehintMatch['typehint'];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function getOptionalSign()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '7.1.0-dev', '>=') && $this->rfp->allowsNull() && !$this->rfp->isVariadic()) {
|
||||
return '?';
|
||||
}
|
||||
|
||||
return '';
|
||||
return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some internal classes have funny looking definitions...
|
||||
* Get the string representation for the paramater type.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTypeHint()
|
||||
{
|
||||
return Reflector::getTypeHint($this->rfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string representation for the paramater type.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated since 1.3.2 and will be removed in 2.0. Use getTypeHint() instead.
|
||||
*/
|
||||
public function getTypeHintAsString()
|
||||
{
|
||||
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' . static::$parameterCounter++;
|
||||
$name = 'arg' . self::$parameterCounter++;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the parameter is an array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isArray()
|
||||
{
|
||||
return Reflector::isArray($this->rfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variadics only introduced in 5.6
|
||||
* Determine if the parameter is variadic.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVariadic()
|
||||
{
|
||||
return version_compare(PHP_VERSION, '5.6.0') >= 0 && $this->rfp->isVariadic();
|
||||
return $this->rfp->isVariadic();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?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\Generator\StringManipulation\Pass;
|
||||
|
||||
use Mockery\Generator\Method;
|
||||
use Mockery\Generator\Parameter;
|
||||
use Mockery\Generator\MockConfiguration;
|
||||
|
||||
class AvoidMethodClashPass implements Pass
|
||||
{
|
||||
public function apply($code, MockConfiguration $config)
|
||||
{
|
||||
$names = array_map(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
|
||||
);
|
||||
|
||||
$code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code);
|
||||
}
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator\StringManipulation\Pass;
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator\StringManipulation\Pass;
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<?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\Generator\StringManipulation\Pass;
|
||||
|
||||
@@ -19,24 +37,9 @@ class ClassPass implements Pass
|
||||
}
|
||||
|
||||
$className = ltrim($target->getName(), "\\");
|
||||
|
||||
if (!class_exists($className)) {
|
||||
$targetCode = '<?php ';
|
||||
|
||||
if ($target->inNamespace()) {
|
||||
$targetCode.= 'namespace ' . $target->getNamespaceName(). '; ';
|
||||
}
|
||||
|
||||
$targetCode.= 'class ' . $target->getShortName() . ' {} ';
|
||||
|
||||
/*
|
||||
* We could eval here, but it doesn't play well with the way
|
||||
* PHPUnit tries to backup global state and the require definition
|
||||
* loader
|
||||
*/
|
||||
$tmpfname = tempnam(sys_get_temp_dir(), "Mockery");
|
||||
file_put_contents($tmpfname, $targetCode);
|
||||
require $tmpfname;
|
||||
\Mockery::registerFileForCleanUp($tmpfname);
|
||||
\Mockery::declareClass($className);
|
||||
}
|
||||
|
||||
$code = str_replace(
|
||||
|
||||
33
vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ConstantsPass.php
vendored
Normal file
33
vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ConstantsPass.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Mockery\Generator\StringManipulation\Pass;
|
||||
|
||||
use Mockery\Generator\MockConfiguration;
|
||||
|
||||
class ConstantsPass implements Pass
|
||||
{
|
||||
public function apply($code, MockConfiguration $config)
|
||||
{
|
||||
$cm = $config->getConstantsMap();
|
||||
if (empty($cm)) {
|
||||
return $code;
|
||||
}
|
||||
|
||||
if (!isset($cm[$config->getName()])) {
|
||||
return $code;
|
||||
}
|
||||
|
||||
$cm = $cm[$config->getName()];
|
||||
|
||||
$constantsCode = '';
|
||||
foreach ($cm 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";
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user