This commit is contained in:
aschwarz
2023-05-12 12:27:19 +02:00
parent 757c2388de
commit e2f1846f03
1974 changed files with 255998 additions and 0 deletions

View File

@ -0,0 +1,7 @@
languages:
PHP: true
exclude_paths:
- "docs/*"
- "bin/*"
- "tests/*"
- "vendor/*"

View File

@ -0,0 +1,12 @@
.buildpath
.project
.settings
.idea
nbproject
vendor
bin
composer.lock
composer.phar
phpunit.xml
docs/_build
rtd-docs/_build

View File

@ -0,0 +1,18 @@
filter:
paths: [src/*]
excluded_paths: [vendor/*, tests/*]
before_commands:
- 'composer install --dev --prefer-source'
tools:
external_code_coverage: true
php_mess_detector: true
php_code_sniffer: true
sensiolabs_security_checker: true
php_code_coverage: true
php_pdepend: true
php_loc:
enabled: true
excluded_dirs: [vendor, tests]
php_cpd:
enabled: true
excluded_dirs: [vendor, tests]

View File

@ -0,0 +1,67 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
- nightly
env:
- PHPUNIT_VERSION=4.8.*
- PHPUNIT_VERSION=4.8.x-dev
- PHPUNIT_VERSION=5.0.x-dev
- PHPUNIT_VERSION=5.1.x-dev
- PHPUNIT_VERSION=6.0.x-dev
script:
- |
if [[ $TRAVIS_PHP_VERSION = "hhv"* ]]; then
hhvm -vEval.EnableHipHopSyntax=true ./bin/phpunit --coverage-clover=build/logs/clover.xml
else
./bin/phpunit --coverage-clover=build/logs/clover.xml
fi
-
matrix:
allow_failures:
- php: nightly
- env: PHPUNIT_VERSION=4.8.x-dev
- env: PHPUNIT_VERSION=5.0.x-dev
- env: PHPUNIT_VERSION=5.1.x-dev
- env: PHPUNIT_VERSION=6.0.x-dev
exclude:
- php: 5.3
env: PHPUNIT_VERSION=5.0.x-dev
- php: 5.4
env: PHPUNIT_VERSION=5.0.x-dev
- php: 5.5
env: PHPUNIT_VERSION=5.0.x-dev
- php: 5.3
env: PHPUNIT_VERSION=5.1.x-dev
- php: 5.4
env: PHPUNIT_VERSION=5.1.x-dev
- php: 5.5
env: PHPUNIT_VERSION=5.1.x-dev
- php: 5.3
env: PHPUNIT_VERSION=6.0.x-dev
- php: 5.4
env: PHPUNIT_VERSION=6.0.x-dev
- php: 5.5
env: PHPUNIT_VERSION=6.0.x-dev
- php: 5.6
env: PHPUNIT_VERSION=6.0.x-dev
- php: hhvm
env: PHPUNIT_VERSION=6.0.x-dev
install:
- composer require --dev phpunit/phpunit:${PHPUNIT_VERSION}
- composer install --dev
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml
- CODECLIMATE_REPO_TOKEN=74f9cd376c20c19d09d6c73e4bac9dad48209fa7f3fb44b650ec7d70db81a51a ./bin/test-reporter

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e
set -o pipefail
if [ "$TRAVIS_PHP_VERSION" = "hhvm" ]; then
# Install the nightly build of HHVM ...
curl http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -
echo deb http://dl.hhvm.com/ubuntu precise main | sudo tee /etc/apt/sources.list.d/hhvm.list
sudo apt-get update
sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install hhvm-nightly
hhvm --version
# Ensure the PHP symlink points to the nightly HHVM build ...
PHP_PATH=$(which php)
HHVM_PATH=$(which hhvm)
sudo rm "$PHP_PATH"
sudo ln -s "$HHVM_PATH" "$PHP_PATH"
echo
php --version
fi

View File

@ -0,0 +1,20 @@
## What's New in 2.1.0
### New Features
**#158 - Allow direct calling of protected methods for mocks**
Allow for calling of private and protected methods on mocks using new Phake::makeVisible() and Phake::makeStaticsVisible() wrappers. This will allow for slightly easier testing of legacy code and abstracts. http://phake.readthedocs.org/en/2.1/mocks.html#calling-private-and-protected-methods-on-mocks
### Changes
**#178 - Renamed thenGetReturnByLambda to thenReturnCallback**
The thenGetReturnByLambda just didn't quite sound right and was difficult to remember so we changed the name. While the original method will still work, a deprecation error will be emitted by the code when thenGetReturnByLambda is called with a message that you should use thenReturnCallback instead. The great news is that no other project in their right mind would ever use that method name, so a search and replace should be pretty reliable.
**#144 - Improve Phake::verify error message**
When a method doesn't match you will now be given a more appropriate diff as to why. This should help make life a little easier when debugging failing tests.
**Enhanced integration with Travis-CI**
We are now testing all the things!
**Integrated with Scrutenizer**
We are also measuring all the things

View File

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

View File

@ -0,0 +1,53 @@
Phake
=======
[![Documentation Status](https://readthedocs.org/projects/phake/badge/?version=2.1)](https://readthedocs.org/projects/phake/?badge=2.1)
[![Build Status](https://secure.travis-ci.org/mlively/Phake.png)](http://travis-ci.org/mlively/Phake)
[![Latest Stable Version](https://poser.pugx.org/phake/phake/v/stable.png)](https://packagist.org/packages/phake/phake) [![Total Downloads](https://poser.pugx.org/phake/phake/downloads.png)](https://packagist.org/packages/phake/phake) [![Latest Unstable Version](https://poser.pugx.org/phake/phake/v/unstable.png)](https://packagist.org/packages/phake/phake) [![License](https://poser.pugx.org/phake/phake/license.png)](https://packagist.org/packages/phake/phake)
Phake is a framework for PHP that aims to provide mock objects, test doubles
and method stubs.
Phake was inspired by a lack of flexibility and ease of use in the current
mocking frameworks combined with a recent experience with Mockito for Java.
A key conceptual difference in mocking between Phake and most of php mocking
frameworks (ie: mock functionality in PHPUnit, PHPMock, and mock functionality
in SimpleTest) is that Phake (like Mockito) employs a verification strategy to
ensure that calls get made. That is to say, you call your code as normal and
then after you have finished the code being tested you can verify whether or
not expected methods were called. This is very different from the
aforementioned products for php which use an expectation strategy where you
lay out your expectations prior to any calls being made.
Installation - Composer
-----------------------
Phake can be installed using [Composer](https://github.com/composer/composer).
1. Add Phake as a dependency.
You'll usually want this as a development dependency, so the example shows it
in the require-dev section.
``` json
"require-dev": {
"phake/phake": "2.*"
}
```
2. Run Composer: `php composer.phar install --dev` or `php composer.phar update phake/phake`
Installation - Source
---------------------
You can also of course install it from source by downloading it from our github repository: https://github.com/mlively/Phake
Links
-------------
There are a few links that have information on how you can utilize Phake.
* [Phake Documentation](http://phake.readthedocs.org/en/latest/)
* [Initial Phake Announcement](http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html)
If you have an article or tutorial that you would like to share, feel free to open an [issue](https://github.com/mlively/Phake/issues) on github and I will add it to this list

View File

@ -0,0 +1,44 @@
{
"name": "phake/phake",
"type": "library",
"description": "The Phake mock testing library",
"keywords": ["testing", "mock"],
"homepage": "https://github.com/mlively/Phake",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Mike Lively",
"email": "m@digitalsandwich.com"
}
],
"require": {
"php": ">=5.3.3",
"sebastian/comparator": "~1.1"
},
"require-dev": {
"ext-soap": "*",
"doctrine/common": "2.3.*",
"phpunit/phpunit": "3.7.*",
"hamcrest/hamcrest-php": "1.1.*",
"codeclimate/php-test-reporter": "dev-master"
},
"config": {
"bin-dir": "bin"
},
"autoload": {
"psr-0": {
"Phake": "src/"
}
},
"suggest": {
"doctrine/common": "Allows mock annotations to use import statements for classes.",
"hamcrest/hamcrest-php": "Use Hamcrest matchers."
},
"extra": {
"branch-alias": {
"dev-master": "3.0.0-dev"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@ -0,0 +1,89 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
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 " 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 " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@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."
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/Phake-PHPMockingFramework.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Phake-PHPMockingFramework.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
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."

View File

@ -0,0 +1,163 @@
.. _answers:
*******
Answers
*******
In all of the examples so far, the ``thenReturn()`` answer is being used. There are other answers that are remarkably
useful writing your tests.
Throwing Exceptions
===================
Exception handling is a common aspect of most object oriented systems that should be tested. The key to being able to
test your exception handling is to be able to control the throwing of your exceptions. Phake allows this using the
``thenThrow()`` answer. This answer allows you to throw a specific exception from any mocked method. Below is an
example of a piece of code that catches an exception from the method foo() and then logs a message with the exception
message.
.. code-block:: php
class MyClass
{
private $logger;
public function __construct(LOGGER $logger)
{
$this->logger = $logger;
}
public function processSomeData(MyDataProcessor $processor, MyData $data)
{
try
{
$processor->process($data);
}
catch (Exception $e)
{
$this->logger->log($e->getMessage());
}
}
}
In order to test this we must mock ``foo()`` so that it throws an exception when it is called. Then we can verify that
``log()`` is called with the appropriate message.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testProcessSomeDataLogsExceptions()
{
$logger = Phake::mock('LOGGER');
$data = Phake::mock('MyData');
$processor = Phake::mock('MyDataProcessor');
Phake::when($processor)->process($data)->thenThrow(new Exception('My error message!'));
$sut = new MyClass($logger);
$sut->processSomeData($processor, $data);
//This comes from the exception we created above
Phake::verify($logger)->log('My error message!');
}
}
.. _then-call-parent:
Calling the Parent
==================
Phake provides the ability to allow calling the actual method of an object on a method by method
basis by using the ``thenCallParent()`` answer. This will result in the actual method being called.
Consider the following class.
.. code-block:: php
class MyClass
{
public function foo()
{
return '42';
}
}
The ``thenCallParent()`` answer can be used here to ensure that the actual method in the class is
called resulting in the value 42 being returned from calls to that mocked method.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testCallingParent()
{
$mock = Phake::mock('MyClass');
Phake::when($mock)->foo()->thenCallParent();
$this->assertEquals(42, $mock->foo());
}
}
Please avoid using this answer as much as possible especially when testing newly written code. If you find yourself
requiring a class to be only partially mocked then that is a code smell for a class that is likely doing too much. An
example of when this is being done is why you are testing a class that has a singular method that has a lot of side
effects that you want to mock while you allow the other methods to be called as normal. In this case that method that
you are desiring to mock should belong to a completely separate class. It is obvious by the very fact that you are able
to mock it without needing to mock other messages that it performs a different function.
Even though partial mocking should be avoided with new code, it is often very necessary to allow creating tests while
refactoring legacy code, tests involving 3rd party code that cant be changed, or new tests of already written code
that cannot yet be changed. This is precisely the reason why this answer exists and is also why it is not the default
answer in Phake.
Capturing a Return Value
========================
Another tool in Phake for testing legacy code is the ``captureReturnTo()`` answer. This performs a function similar to
argument capturing, however it instead captures what the actual method of a mock object returns to the variable passed
as its parameter. Again, this should never be needed if you are testing newly written code. However I have ran across
cases several times where legacy code calls protected factory methods and the result of the method call is never
exposed. This answer gives you a way to access that variable to ensure that the factory was called and is operating
correctly in the context of your method that is being tested.
Answer Callbacks
================
While the answers provided in Phake should be able to cover most of the scenarios you will run into when using mocks in
your unit tests there may occasionally be times when you need more control over what is returned from your mock
methods. When this is the case, you can use a callback answer. These do generally increase the complexity of tests and
you really should only use them if you won't know what you need to return until call time.
You can specify a callback answer using the thenReturnCallback method. This argument takes a callback or a closure.
The callback will be passed the same arguments as were passed to the method being stubbed. This allows you to use them
to help determine the answer.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testCallback()
{
$mock = Phake::mock('MyClass');
Phake::when($mock)->foo->thenReturnCallback(function ($val) { return $val * 2; });
$this->assertEquals(42, $mock->foo(21));
}
}
Custom Answers
==============
You can also create custom answers. All answers in Phake implement the ``Phake_Stubber_IAnswer`` interface. This
interface defines a single method called ``getAnswer()`` that can be used to return what will be returned from a call
to the method being stubbed. If you need to get access to how the method you are stubbing was invoked, there is a more
complex set of interfaces that can be implemented: ``Phake_Stubber_Answers_IDelegator`` and
``Phake_Stubber_IAnswerDelegate``.
``Phake_Stubber_Answers_IDelegator`` extends ``Phake_Stubber_IAnswer`` and defines an additional method called
``processAnswer()`` that is used to perform processing on the results of ``getAnswer()`` prior to passing it on to the
stubs caller. ``Phake_Stubber_IAnswerDelegate`` defines an interface that allows you to create a callback that is
called to generate the answer from the stub. It defines ``getCallBack()`` which allows you to generate a PHP callback
based on the object, method, and arguments that a stub was called with. It also defines ``getArguments()`` which allows
you to generate the arguments that will be passed to the callback based on the method name and arguments the stub was
called with.

View File

@ -0,0 +1,194 @@
# -*- coding: utf-8 -*-
#
# Phake - PHP Mocking Framework documentation build configuration file, created by
# sphinx-quickstart on Wed Apr 2 02:02:12 2014.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Phake - PHP Mocking Framework'
copyright = u'2014, Mike Lively <m@digitalsandwich.com>'
# 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 = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'Phake-PHPMockingFrameworkdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Phake-PHPMockingFramework.tex', u'Phake - PHP Mocking Framework Documentation',
u'Mike Lively \\textless{}m@digitalsandwich.com\\textgreater{}', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

View File

@ -0,0 +1,51 @@
*************
Configuration
*************
There are some options you can use to configure and customize Phake. None of these options are required and
Phake can always just be used straight out of the box, however some configuration options are available to
provide more convenient integration with PHPUnit and ability to debug your mock objects.
Setting the Phake Client
========================
While Phake does not have a direct dependency on PHPUnit, there is a PHPUnit specific client that improves
error reporting and allows you to utilize strict mode with PHPUnit. Without using the PHPUnit client, any
failed verifications will result in an errored test. Generally speaking, with PHPUnit, the error result is
reserved for bad tests, not failed tests.
The other issue you would run into when using Phake with PHPUnit without using the PHPUnit Phake client is
that any test runs utilizing the --strict flag will fail when an assertion is not recorded. By default Phake
does not register assertions with PHPUnit. When the PHPUnit client is used however, the assertions are
recorded and --strict mode can be safely used with your tests.
To enable the PHPUnit Phake client, you can register it in your test bootstrap.
.. code-block:: php
require_once('Phake.php');
Phake::setClient(Phake::CLIENT_PHPUNIT);
Setting the Mock Class Loader
=============================
When generating mock classes, Phake will load them into memory utilizing the PHP ``eval()`` function. This can
make the code inside of mock classes difficult to debug or diagnose when errors occur in this code. Using
the ``Phake::setMockLoader()`` method you can change this behavior to instead dump the generated class to a
file and then require that file. This will allow for accurate and easily researchable errors when running
tests. This shouldn't typically be required for most users of Phake, however if your are having errors or
working on code for Phake itself it can be incredibly useful.
``Phake::setMockLoader()`` accepts a single parameter of type ``Phake_ClassGenerator_ILoader``. The default
behavior is contained in the ``Phake_ClassGenerator_EvalLoader`` class. If you would instead like to dump the
classes to files you can instead use the ``Phake_ClassGenerator_FileLoader`` class. The constructor accepts a
single parameter containing the directory you would like to dump the classes to. The classes will be stored
in files with the same name as the generated class.
Below is an example of the code required to dump mock classes into the /tmp folder.
.. code-block:: php
require_once('Phake.php');
require_once('Phake/ClassGenerator/FileLoader.php');
Phake::setMockLoader(new Phake_ClassGenerator_FileLoader('/tmp'));

View File

@ -0,0 +1,39 @@
Getting Started
===============
Phake depends on PHP 5.3.3 or greater. It has no dependency on PHPUnit and should be usable with
any version of PHPUnit so long as the PHP version is 5.3.3 or greater.
Composer Install
----------------
Phake can be installed via `Composer <https://github.com/composer/composer>`_. You will typically want to install Phake
as a development requirement. To do so you can add the following to your ``composer.json`` file:
.. code-block:: js
{
// ..
"require-dev": {
"phake/phake": "@stable"
}
// ..
}
Once this is added to ``composer.json`` you can run ``composer update phake/phake``
Install from Source
-------------------
You can also clone a copy of Phake from the `Phake GitHub repository <https://github.com/mlively/Phake>`_.
Every attempt is made to keep the master branch stable and this should be usable for those that
immediately need features before they get released or in the event that you enjoy the bleeding edge.
Always remember, until something goes into a rc state, there is always a chance that the functionality
may change. However as an early adopter that uses GitHub, you can have a chance to mold the software
as it is built.
Support
-------
If you think you have found a bug or an issue with Phake, please feel free to open up an issue on the
`Phake Issue Tracker <https://github.com/mlively/Phake/issues>`_

View File

@ -0,0 +1,28 @@
.. Phake - PHP Mocking Framework documentation master file, created by
sphinx-quickstart on Wed Apr 2 02:02:12 2014.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Phake - PHP Mocking Framework's documentation!
=========================================================
.. toctree::
:maxdepth: 2
introduction
getting-started
mocks
method-stubbing
method-verification
mocking-statics
answers
method-parameter-matchers
configuration
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,144 @@
Introduction to Phake
=====================
**Phake** is a mocking framework for PHP. It allows for the creation of objects that mimic a real
object in a predictable and controlled manner. This allows you to treat external method calls
made by your system under test (SUT) as just another form of input to your SUT and output from
your SUT. This is done by stubbing methods that supply indirect input into your test and by
verifying parameters to methods that receive indirect output from your test.
In true Las Vegas spirit I am implementing a new framework that allows you to easily create
new card games. Most every card game at one point or another needs a dealer. In the example below
I have created a new class called ``CardGame`` that implements the basic functionality for a card game:
.. code-block:: php
class CardGame
{
private $dealerStrategy;
private $deck;
private $players;
public function CardGame(DealerStrategy $dealerStrategy, CardCollection $deck, PlayerCollection $players)
{
$this->dealerStrategy = $dealerStrategy;
$this->deck = $deck;
$this->players = $players;
}
public function dealCards()
{
$this->deck->shuffle();
$this->dealerStrategy->deal($deck, $players);
}
}
If I want to create a new test to ensure that ``dealCards()`` works properly, what do I need to test?
Everything I read about testing says that I need to establish known input for my test, and then
test its output. However, in this case, I dont have any parameters that are passed into ``dealCards()``
nor do I have any return values I can check. I could just run the ``dealCards()`` method and make sure
I dont get any errors or exceptions, but that proves little more than my method isnt blowing up
spectacularly. It is apparent that I need to ensure that what I actually assert is that
the ``shuffle()`` and ``deal()`` methods are being called. If
I want to continue testing this using concrete
classes that already exist in my system, I could conjure up one of my implementations of ``DealerStrategy``,
``CardCollection`` and ``PlayerCollection``. All of those
objects are closer to being true value objects
with a testable state. I could feasibly construct instances of those objects, pass them into an
instance of ``CardGame``, call ``dealCards()`` and then assert
the state of those same objects. A test doing
this might look something like:
.. code-block:: php
class CardGameTest1 extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = new FiveCardPokerDealer();
$deck = new StandardDeck();
$player1 = new Player();
$player2 = new Player();
$player3 = new Player();
$player4 = new Player();
$players = new PlayerCollection(array($player1, $player2, $player3, $player4));
$cardGame = new CardGame($dealer, $deck, $players);
$cardGame->dealCards();
$this->assertEquals(5, count($player1->getCards()));
$this->assertEquals(5, count($player2->getCards()));
$this->assertEquals(5, count($player3->getCards()));
$this->assertEquals(5, count($player4->getCards()));
}
}
This test isnt all that bad, its not difficult to understand and it does make sure that cards
are dealt through making sure that each player has 5 cards. There are at least two significant problems
with this test however. The first problem is that there is not any isolation of the SUT which in
this case is ``dealCards()``. If something is broken in the ``FiveCardPokerDealer``
class, the ``Player`` class,
or the ``PlayerCollection`` class, it will manifest itself here as a broken ``CardGame``
class. Thinking
about how each of these classes might be implemented, one could easily make the argument that this
really tests the ``FiveCardPokerDealer`` class much more than the ``dealCards()`` method.
The second problem
is significantly more problematic. It is perfectly feasible that I could remove the call to ``$this->deck->shuffle()``
in my SUT and the test I have created will still test just fine. In order to solidify my test I
need to introduce logic to ensure that the deck has been shuffled. With the current mindset of using
real objects in my tests I could wind up with incredibly complicated logic. I could feasibly add
an identifier of some sort to ``DealerStrategy::shuffle()`` to mark the deck as shuffled thereby making
it checkable state, however that makes my design more fragile as I would have to ensure that identifier
was set probably on every implementation of ``DealerStrategy::shuffle()``.
This is the type of problem that mock frameworks solve. A mock framework such as Phake can
be used to create implementations of my ``DealerStrategy``, ``CardCollection``, and ``PlayerCollection`` classes.
I can then exercise my SUT. Finally, I can verify that the methods that should be called on these
objects were called correctly. If this test were
re-written to use Phake, it would become:
.. code-block:: php
class CardGameTest2 extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = Phake::mock('DealerStrategy');
$deck = Phake::mock('CardCollection');
$players = Phake::mock('PlayerCollection');
$cardGame = new CardGame($dealer, $deck, $players);
$cardGame->dealCards();
Phake::verify($deck)->shuffle();
Phake::verify($dealer)->deal($deck, $players);
}
}
There are three benefits of using mock objects that can be seen through this example. The first benefit
is that the brittleness of the fixture is reduced. In our previous example you see that I have to construct
a full object graph based on the dependencies of all of the classes involved. I am fortunate in
the first example that there are only 4 classes involved. In real world problems and especially
long lived, legacy code the object graphs can be much, much larger. When using mock objects you
typically only have to worry about the direct dependencies of your SUT. Specifically, direct dependencies
required to instantiate the dependencies of the class under test, the parameters passed to the method
under test (direct dependencies,) and the values returned by additional method calls within the
method under test (indirect dependencies.)
The second benefit is the test is only testing the SUT. If this test fails due to a change in anything
but the interfaces of the classes involved, the change would have had to been made in either the
constructor of ``CardGame``, or the ``dealCards()`` method itself.
Obviously, if an interface change is
made (such as removing the ``shuffle()``) method, then I would have a scenario
where the changed code is outside of this class. However, provided the removal of that method was
intentional, I will know that this code needs to be addressed as it is depending on a method that no longer exists.
The third benefit is that I have truer verification and assertions of the outcome of exercising
my SUT. In this case for instance, I can be sure that if the call to ``shuffle()`` is removed, this
test will fail. It also does it in a way that keeps the code necessary to assert your final state
simple and concise. This makes my test overall much easier to understand and maintain. There is
still one flaw with this example however. There is nothing here to ensure that ``shuffle()`` is called
before ``deal()`` it is quite possible for someone to mistakenly reverse the order of these two calls.
The Phake framework does have the ability to track call order to make this test even more bullet
proof via the ``Phake::inOrder()`` method. I will go over this in more detail later.

View File

@ -0,0 +1,340 @@
.. _method-parameter-matchers-section:
*************************
Method Parameter Matchers
*************************
The verification and stubbing functionality in Phake both rely heavily on parameter matching to help the system
understand exactly which calls need to be verified or stubbed. Phake provides several options for setting up parameter
matches.
The most common scenario for matching parameters as you use mock objects is matching on equal variables For this reason
the default matcher will ensure that the parameter you pass to the mock method is equal (essentially using the '=='
notation) to the parameter passed to the actual invocation before validating the call or returning the mocked stub. So
going back to the card game demonstration from the introduction. Consider the following interface:
.. code-block:: php
interface DealerStrategy
{
public function deal(CardCollection $deck, PlayerCollection $players);
}
Here we have a ``deal()`` method that accepts two parameters. If you want to verify that ``deal()`` was called, chances
are very good that you want to verify the the parameters as well. To do this is as simple as passing those parameters
to the ``deal()`` method on the ``Phake::verify($deal)`` object just as you would if you were calling the actual
``deal()`` method itself. Here is a short albeit silly example:
.. code-block:: php
//I don't have Concrete versions of
// CardCollection or PlayerCollection yet
$deck = Phake::mock('CardCollection');
$players = Phake::mock('PlayerCollection');
$dealer = Phake::mock('DealerStrategy');
$dealer->deal($deck, $players);
Phake::verify($dealer)->deal($deck, $players);
In this example, if I were to have accidentally made the call to ``deal()`` with a property that was set to null as the
first parameter then my test would fail with the following exception::
Expected DealerStrategy->deal(equal to
<object:CardCollection>, equal to <object:PlayerCollection>)
to be called exactly 1 times, actually called 0 times.
Other Invocations:
PhakeTest_MockedClass->deal(<null>,
equal to <object:PlayerCollection>)
Determining the appropriate method to stub works in exactly the same way.
There may be cases when it is necessary to verify or stub parameters based on something slightly more complex then
basic equality. This is what we will talk about next.
Using PHPUnit Matchers
======================
Phake was developed with PHPUnit in mind. It is not dependent on PHPUnit, however if PHPUnit is your testing framework
of choice there is some special integration available. Any constraints made available by the PHPUnit framework will
work seamlessly inside of Phake. Here is an example of how the `PHPUnit constraints <https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertThat.tables.constraints>`_ can be used:
.. code-block:: php
class TestPHPUnitConstraint extends PHPUnit_Framework_TestCase
{
public function testDealNumberOfCards()
{
$deck = Phake::mock('CardCollection');
$players = Phake::mock('PlayerCollection');
$dealer = Phake::mock('DealerStrategy');
$dealer->deal($deck, $players, 11);
Phake::verify($dealer)
->deal($deck, $players, $this->greaterThan(10));
}
}
I have added another parameter to my ``deal()`` method that allows me to specify the number of cards to deal to each
player. In the test above I wanted to verify that the number passed to this parameter was greater than 10.
For a list of the constraints you have available to you through PHPUnit, I recommend reading the PHPUnit's
documentation on assertions and constraints. Any constraint that can be used with ``assertThat()`` in PHPUnit can also
be used in Phake.
Using Hamcrest Matchers
=======================
If you do not use PHPUnit, Phake also supports `Hamcrest matchers <https://github.com/hamcrest/hamcrest-php#this-is-the-php-port-of-hamcrest-matchers>`_. This is in-line with the Phake's design goal of being
usable with any testing framework. Here is a repeat of the PHPUnit example, this time using SimpleTest and Hamcrest
matchers.
.. code-block:: php
class TestHamcrestMatcher extends UnitTestCase
{
public function testDealNumberOfCards()
{
$deck = Phake::mock('CardCollection');
$players = Phake::mock('PlayerCollection');
$dealer = Phake::mock('DealerStrategy');
$dealer->deal($deck, $players, 11);
Phake::verify($dealer)->deal($deck, $players, greaterThan(10));
}
}
.. _wildcard-parameters:
Wildcard Parameters
===================
Frequently when stubbing methods, you do not really care about matching parameters. Often times matching every
parameter for a stub can result in overly brittle tests. If you find yourself in this situation you can use Phake's
shorthand stubbing to instruct Phake that a mock should be stubbed on any invocation. You could also use it to verify a
method call regardless of parameters. This is not a very common use case but it is possible.
To specify that a given stub or verification method should match any parameters, you call the method you are stubbing
or mocking as a property of ``Phake::when()`` or ``Phake::verify()``. The code below will mock any invocation of
$obj->foo() regardless of parameters to return bar.
.. code-block:: php
class FooTest extends PHPUnit_Framework_TestCase
{
public function testAddItemsToCart()
{
$obj = Phake::mock('MyObject');
Phake::when($obj)->foo->thenReturn('bar');
$this->assertEquals('bar', $obj->foo());
$this->assertEquals('bar', $obj->foo('a parameter'));
$this->assertEquals('bar', $obj->foo('multiple', 'parameters'));
}
}
If you are familiar with ``Phake::anyParameters()`` then you will recognize that the shorthand functionality is really
just short hand of ``Phake::anyParameters()``. You can still use ``Phake::anyParameters()`` but it will likely be
deprecated at some point in the future.
Default and Variable Parameters
-------------------------------
Wildcards can also come in handy when stubbing or verifying methods with default parameters or variable parameters. In
addition to ``Phake::anyParameters()``, ``Phake::ignoreRemaining()`` can be used to instruct Phake to not attempt to
match any further parameters.
A good example of where this could be handy is if you are mocking or verifying a method where the first parameter is
important to stubbing but maybe the remaining parameters aren't. The code below stubs a factory method where the first
parameter sets an item's name, but the remaining parameters are all available as defaults.
.. code-block:: php
class MyFactory
{
public function createItem($name, $color = 'red', $size = 'large')
{
//...
}
}
class MyTest extends PHPUnit_Framework_TestCase
{
public function testUsingItemFactory()
{
$factory = Phake::mock('MyFactory');
$factory->createItem('Item1', 'blue', 'small');
//Verification below will succeed
Phake::verify($factory)->createItem('Item1', Phake::ignoreRemaining());
}
}
Parameter Capturing
===================
As you can see there are a variety of methods for verifying that the appropriate parameters are being passed to
methods. However, there may be times when the prebuilt constraints and matchers simply do not fit your needs. Perhaps
there is method that accepts a complex object where only certain components of the object need to be validated.
Parameter capturing will allow you to store the parameter that was used to call your method so that it can be used in
assertions later on.
Consider the following example where I have defined a ``getNumberOfCards()`` method on the ``CardCollection`` interface.
.. code-block:: php
interface CardCollection
{
public function getNumberOfCards();
}
I want to create new functionality for a my poker dealer strategy that will check to make sure we are playing with a
full deck of 52 cards when the ``deal()`` call is made. It would be rather cumbersome to create a copy of a
``CardCollection`` implementation that I could be sure would match in an equals scenario. Such a test would look
something like this.
Please note, I do not generally advocate this type of design. I prefer dependency injection to instantiation. So
please remember, this is not an example of clean design, simply an example of what you can do with argument capturing.
.. code-block:: php
class MyPokerGameTest extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = Phake::mock('MyPokerDealer');
$players = Phake::mock('PlayerCollection');
$cardGame = new MyPokerGame($dealer, $players);
Phake::verify($dealer)->deal(Phake::capture($deck), $players);
$this->assertEquals(52, $deck->getNumberOfCards());
}
}
You can also capture parameters if they meet a certain condition. For instance, if someone mistakenly passed an array
as the first parameter to the ``deal()`` method then PHPUnit would fatal error out. This can be protected against by
using the the ``Phake::capture()->when()`` method. The ``when()`` method accepts the same constraints that
``Phake::verify()`` accepts. Here is how you could leverage that functionality to bulletproof your captures a little
bit.
.. code-block:: php
class MyBetterPokerGameTest extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = Phake::mock('MyPokerDealer');
$players = Phake::mock('PlayerCollection');
$cardGame = new MyPokerGame($dealer, $players);
Phake::verify($dealer)->deal(
Phake::capture($deck)
->when($this->isInstanceOf('CardCollection')),
$players
);
$this->assertEquals(52, $deck->getNumberOfCards());
}
}
This could also be done by using PHPUnit's assertions later on with the captured parameter, however this also has a
side effect of better localizing your error. Here is the error you would see if the above test failed.
::
Exception: Expected MyPokerDealer->deal(<captured parameter>,
equal to <object:PlayerCollection>) to be called exactly 1
times, actually called 0 times.
Other Invocations:
PhakeTest_MockedClass->deal(<array>,
<object:PlayerCollection>)
It should be noted that while it is possible to use argument capturing for stubbing with ``Phake::when()`` I would
discourage it. When stubbing a method, you should only be concerned about making sure an expected value is returned.
Argument capturing in no way helps with that goal. In the worst case scenario, you will have some incredibly difficult
test failures to diagnose.
Beginning in Phake 2.1 you can also capture all values for a given parameter for every matching invocation. For
instance imagine if you have a method ``$foo->process($eventManager)`` that should send a series of events.
.. code-block:: php
class Foo
{
// ...
public function process(Request $request, EventManager $eventManager)
{
$eventManager->fire(new PreProcessEvent($request));
// ... do stuff
$eventManager->fire(new PostProcessEvent($request, $result));
}
}
If you wanted to verify different aspects of the ``$eventManager->fire()`` calls this would have been very difficult
and brittle using standard argument captors. There is now a new method ``Phake::captureAll()`` that can be used to
capture all otherwise matching invocations of method. The variable passed to ``Phake::captureAll()`` will be set to an
array containing all of the values used for that parameter. So with this function the following test can be written.
.. code-block:: php
class FooTest
{
public function testProcess()
{
$foo = new Foo();
$request = Phake::mock('Request');
$eventManager = Phake::mock('EventManager');
$foo->process($request, $eventManager);
Phake::verify($eventManager, Phake::atLeast(1))->fire(Phake::captureAll($events));
$this->assertInstanceOf('PreProcessEvent', $events[0]);
$this->assertEquals($request, $events[0]->getRequest());
$this->assertInstanceOf('PostProcessEvent', $events[1]);
$this->assertEquals($request, $events[1]->getRequest());
}
}
Custom Parameter Matchers
=========================
An alternative to using argument capturing is creating custom matchers. All parameter matchers implement the interface
``Phake_Matchers_IArgumentMatcher``. You can create custom implementations of this interface. This is especially useful
if you find yourself using a similar capturing pattern over and over again. If I were to rewriting the test above using
a customer argument matcher it would look something like this.
.. code-block:: php
class FiftyTwoCardDeckMatcher implements Phake_Matchers_IArgumentMatcher
{
public function matches(&$argument)
{
return ($argument instanceof CardCollection
&& $argument->getNumberOfCards() == 52);
}
public function __toString()
{
return '<object:CardCollection with 52 cards>';
}
}
class MyBestPokerGameTest extends PHPUnit_Framework_TestCase
{
public function testDealCards()
{
$dealer = Phake::mock('MyPokerDealer');
$players = Phake::mock('PlayerCollection');
$cardGame = new MyPokerGame($dealer, $players);
Phake::verify($dealer)->deal(new FiftyTwoCardDeckMatcher(), $players);
}
}

View File

@ -0,0 +1,808 @@
.. _method-stubbing-section:
Method Stubbing
===============
The ``Phake::when()`` method is used to stub methods in Phake. As discussed in the introduction,
stubbing allows an object method to be forced to return a particular value given a set of parameters. Similarly to
``Phake::verify()``, ``Phake::when()`` accepts a mock object generated from
``Phake::mock()`` as its first parameter.
Imagine I was in the process of building the next great online shopping cart. The first thing any
good shopping cart allows is to be able to add items. The most important thing I want to know from
the shopping cart is how much money in merchandise is in there. So, I need to make myself a
ShoppingCart class. I also am going to need some class to define my items.
I am more worried about the money right now and because of that I am keenly aware that any item
in a shopping cart is going to have a price. So I will just create an interface to represent those
items called Item. Now take a minute to marvel at the creativity of those
names. Great, now check out the initial definitions for my objects.
.. code-block:: php
/**
* An item that is going to make me rich.
*/
interface Item
{
/**
* @return money
*/
public function getPrice();
}
/**
* A customer's cart that will contain items that are going to make me rich.
*/
class ShoppingCart
{
private $items = array();
/**
* Adds an item to the customer's order
* @param Item $item
*/
public function addItem(Item $item)
{
$this->items[] = $item;
}
/**
* Returns the current sub total of the customer's order
* @return money
*/
public function getSubTotal()
{
}
}
So, I am furiously coding away at this fantastic new ``ShoppingCart`` class when I
realize, I am doing it wrong! You see, a few years ago I went to this conference with a bunch of
other geeky people to talk about how to make quality software. I am supposed to be writing unit
tests. Here I am, a solid thirteen lines (not counting comments) of code into my awe inspiring
new software and I haven't written a single test. I tell myself, "There's no better time to change
than right now!" So I decide to start testing. After looking at the options I decide PHPUnit with
this sweet new mock library called Phake is the way to go.
My first test is going to be for the currently unimplemented ``ShoppingCart::getSubTotal()``
method. I already have a pretty good idea of what this function is going to need to do. It will
need to look at all of the items in the cart, retrieve their price, add it all together and return
the result. So, in my test I know I am going to need a fixture that sets up a shopping cart with
a few items added. Then I am going to need a test that calls ``ShoppingCart::getSubTotal()``
and asserts that it returns a value equal to the price of the items I added to the cart. One catch
though, I don't have any concrete instances of an ``Item``. I wasn't even planning on doing any of
that until tomorrow. I really want to just focus on the ``ShoppingCart`` class.
Never fear, this is why I decided to use Phake. I remember reading about how it will allow me to
quickly create instance of my classes and interfaces that I can set up stubs for so that method
calls return predictable values. This project is all coming together and I am really excited.
.. code-block:: php
class ShoppingCartTest extends PHPUnit_Framework_TestCase
{
private $shoppingCart;
private $item1;
private $item2;
private $item3;
protected function setUp()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
Phake::when($this->item1)->getPrice()->thenReturn(100);
Phake::when($this->item2)->getPrice()->thenReturn(200);
Phake::when($this->item3)->getPrice()->thenReturn(300);
$this->shoppingCart = new ShoppingCart();
$this->shoppingCart->addItem($this->item1);
$this->shoppingCart->addItem($this->item2);
$this->shoppingCart->addItem($this->item3);
}
public function testGetSub()
{
$this->assertEquals(600, $this->shoppingCart->getSubTotal());
}
}
My test here shows a very basic use of Phake for creating method stubs. I am creating three different mock
implementations of the ``Item`` class. Then for each of those item classes, I am creating
a stub using ``Phake::when()`` that will return 100, 200, and 300 respectively. I know my method
that I am getting ready to implement will need to call those methods in order to calculate the total cost of the
order.
My test is written so now it is time to see how it fails. I run it with phpunit and see the output below::
$ phpunit ExampleTests/ShoppingCartTest.php
PHPUnit 3.5.13 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 8.50Mb
There was 1 failure:
1) ShoppingCartTest::testGetSub
Failed asserting that <null> matches expected <integer:600>.
/home/mikel/Documents/Projects/Phake/tests/ShoppingCartTest.php:69
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Generating code coverage report, this may take a moment.
Now that I have a working (and I by working I mean breaking!) test it is time to look at the code necessary to make
the test pass.
.. code-block:: php
class ShoppingCart
{
// I am cutting out the already seen code. If you want to see it again look at the previous examples!
/**
* Returns the current sub total of the customer's order
* @return money
*/
public function getSubTotal()
{
$total = 0;
foreach ($this->items as $item)
{
$total += $item->getPrice();
}
return $total;
}
}
The code here is pretty simple. I am just iterating over the ``ShoppingCart::$item`` property,
calling the ``Item::getPrice()`` method, and adding them all together. Now when I run phpunit, the tests were successful
and I am getting off to a great start with my shopping cart.
::
$ phpunit ExampleTests/ShoppingCartTest.php
PHPUnit 3.5.13 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 8.25Mb
OK (1 test, 1 assertion)
Generating code coverage report, this may take a moment.
So, what is Phake doing here? Phake is providing us a predictable implementation of the ``Item::getPrice()``
method that we can use in our test. It helps me to ensure the when my test breaks I know exactly where it is breaking.
I will not have to be worried that a bad implementation of ``Item::getPrice()`` is breaking my tests.
.. _how-phake-when-works:
How Phake::when() Works
-----------------------
Internally Phake is doing quite a bit when this test runs. The three calls to ``Phake::mock()`` are
creating three new classes that in this case each implement the ``Item`` interface. These new classes
each define implementations of any method defined in the ``Item`` interface. If ``Item``
extended another interface, implementations of all of that parent's defined methods would be created as well. Each
method being implemented in these new classes does a few different things. The first thing that it does is record
the fact that the method was called and stores the parameters that were used to call it. The next significant thing
it does is looks at the stub map for that mock object. The stub map is a map that associates answers to method matchers.
An answer is what a mocked object will return when it is called. By default, a call to a mock object returns a static
answer of NULL. We will discuss answers more in :ref:`answers`. A method matcher has two parts. The
first is the method name. The second is an array of arguments. The array of arguments will then contain various constraints
that are applied to each argument to see if a given argument will match. The most common constraint is an equality constraint
that will match loosely along the same lines as the double equals sign in PHP. We will talk about matchers more in
:ref:`method-parameter-matchers-section`.
When each mock object is initially created, its stub map will be empty. This means that any call to a method on a mock object
is going to return a default answer of NULL. If you want your mock object's methods to return something else you must add answers
to the stub map. The ``Phake::when()`` method allows you to map an answer to a method matcher for a given mock object.
The mock object you want to add the mapping to is passed as the first parameter to ``Phake::when()``. The
``Phake::when()`` method will then return a proxy that can be used add answers to your mock object's stub
map. The answers are added by making method calls on the proxy just as you would on the mock object you are proxying. In
the first example above you saw a call to ``Phake::when($this->item1)->getPrice()``.
The ``getPrice()`` call here was telling Phake that I am about to define a new answer that will be returned
any time ``$this->item->getPrice()`` is called in my code. The call to ``$this->item->getPrice()``
returns another object that you can set the answer on using Phake's fluent api. In the example I called
``Phake::when($this->item1)->getPrice()->thenReturn(100)``. The ``thenReturn()`` method will
bind a static answer to a matcher for ``getPrice()`` in the stub map for $this->item1.
Why do Phake stubs return Null by default?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The reasoning behind this is that generally speaking, each method you test should depend on only what it needs to perform the
(hopefully one) responsibility assigned to it. Normally you will have very controlled delegation to other objects. To help with
localization of errors in your test it is assumed that you will always want to mock external dependencies to keep them from
influencing the results of unit tests dedicated to the behavior of other parts of the system. Another reason for this default
behavior is that it provides consistent and predictable behavior regardless of whether you are testing concrete classes, abstract
classes, or interfaces. It should be noted that this default behavior for concrete methods in classes is different then the default
behavior in PHPUnit. In PHPUnit, you have to explicitly indicate that you are mocking a method, otherwise it will call the actual
method code. There are certainly cases where this is useful and this behavior can be achieved in Phake. I will discuss this aspect
of Phake in :ref:`partial-mocks`.
Overwriting Existing Stubs
--------------------------
My shopping cart application is coming right along. I can add items and the total price seems to be accurate. However,
while I was playing around with my new cart I noticed a very strange problem. I was playing around with the idea of
allowing discounts to be applied to a cart as just additional items that would have a negative price. So while I am
playing around with this idea I notice that the math isn't always adding up. If I start with an item that is $100 and
then add a discount that is $81.40 I see that the total price isn't adding up to $18.60. This is definitely problematic
After doing some further research, I realize I made a silly mistake. I am just using simple floats to calculate the
costs. Floats are by nature inaccurate. Once you start using them in mathematical operations they start to show their
inadequacy for precision. In keeping with the test driven method of creating code I need to create a unit test that
shows this flaw.
.. code-block:: php
class ShoppingCartTest extends PHPUnit_Framework_TestCase
{
private $shoppingCart;
private $item1;
private $item2;
private $item3;
public function setUp()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
Phake::when($this->item1)->getPrice()->thenReturn(100);
Phake::when($this->item2)->getPrice()->thenReturn(200);
Phake::when($this->item3)->getPrice()->thenReturn(300);
$this->shoppingCart = new ShoppingCart();
$this->shoppingCart->addItem($this->item1);
$this->shoppingCart->addItem($this->item2);
$this->shoppingCart->addItem($this->item3);
}
public function testGetSub()
{
$this->assertEquals(600, $this->shoppingCart->getSubTotal());
}
public function testGetSubTotalWithPrecision()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
Phake::when($this->item1)->getPrice()->thenReturn(100);
Phake::when($this->item2)->getPrice()->thenReturn(-81.4);
Phake::when($this->item3)->getPrice()->thenReturn(20);
$this->shoppingCart = new ShoppingCart();
$this->shoppingCart->addItem($this->item1);
$this->shoppingCart->addItem($this->item2);
$this->shoppingCart->addItem($this->item3);
$this->assertEquals(38.6, $this->shoppingCart->getSubTotal());
}
}
You can see that I added another test method that uses actual floats for some of the prices as opposed to round numbers.
Now when I run my test suite I can see the fantastic floating point issue.
::
$ phpunit ExampleTests/ShoppingCartTest.php
PHPUnit 3.5.13 by Sebastian Bergmann.
.F
Time: 0 seconds, Memory: 10.25Mb
There was 1 failure:
1) ShoppingCartTest::testGetSubTotalWithPrecision
Failed asserting that <double:38.6> matches expected <double:38.6>.
/home/mikel/Documents/Projects/Phake/tests/ShoppingCartTest.php:95
FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
Generating code coverage report, this may take a moment.
Once you get over the strangeness of 38.6 not equaling 38.6 I want to discuss streamlining test cases with you. You
will notice that the code in ``ShoppingCartTest::testGetSubTotalWithPrecision()`` contains almost
all duplicate code when compared to ``ShoppingCartTest::setUp()``. If I were to continue following
this pattern of doing things I would eventually have tests that are difficult to maintain. Phake allows you to very
easily override stubs. This is very important in helping you to reduce duplication in your tests and leads to tests
that will be easier to maintain. To overwrite a previous stub you simply have to redefine it. I am going to change
``ShoppingCartTest::testGetSubTotalWithPrecision()`` to instead just redefine the ``getPrice()``
stubs.
.. code-block:: php
class ShoppingCartTest extends PHPUnit_Framework_TestCase
{
private $shoppingCart;
private $item1;
private $item2;
private $item3;
public function setUp()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
Phake::when($this->item1)->getPrice()->thenReturn(100);
Phake::when($this->item2)->getPrice()->thenReturn(200);
Phake::when($this->item3)->getPrice()->thenReturn(300);
$this->shoppingCart = new ShoppingCart();
$this->shoppingCart->addItem($this->item1);
$this->shoppingCart->addItem($this->item2);
$this->shoppingCart->addItem($this->item3);
}
public function testGetSub()
{
$this->assertEquals(600, $this->shoppingCart->getSubTotal());
}
public function testGetSubTotalWithPrecision()
{
Phake::when($this->item1)->getPrice()->thenReturn(100);
Phake::when($this->item2)->getPrice()->thenReturn(-81.4);
Phake::when($this->item3)->getPrice()->thenReturn(20);
$this->assertEquals(38.6, $this->shoppingCart->getSubTotal());
}
}
If you rerun this test you will get the same results shown in before.
The test itself is much simpler though there is much less unnecessary duplication. The reason this works is because
the stub map I was referring to in :ref:`how-phake-when-works` isn't really a map at all. It is more of
a stack in reality. When a new matcher and answer pair is added to a mock object, it is added to the top of the stack.
Then whenever a stub method is called, the stack is checked from the top down to find the first matcher that matches
the method that was called. So, when I created the additional stubs for the various ``Item::getPrice()``
calls, I was just adding additional matchers to the top of the stack that would always get matched first by virtue
of the parameters all being the same.
Resetting A Mock's Stubs
------------------------
If overriding a stub does not work for your particular case and you would rather start over with all default stubs then
you can use ``Phake::reset()`` and ``Phake::staticReset()``. These will remove all stubs from a mock and also empty
out all recorded calls against a mock. ``Phake::reset()`` will do this for instance methods on the mock and
``Phake::staticReset()`` will do this for all static methods on the mock.
.. code-block:: php
public function testResettingStubMapper()
{
$mock = Phake::mock('PhakeTest_MockedClass');
Phake::when($mock)->foo()->thenReturn(42);
$this->assertEquals(42, $mock->foo());
Phake::reset($mock);
//$mock->foo() now returns the default stub which in this case is null
$this->assertNull($mock->foo());
}
public function testResettingCallRecorder()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->foo();
//Will work as normal
Phake::verify($mock)->foo();
Phake::reset($mock);
//Will now throw an error that foo was not called
Phake::verify($mock)->foo();
}
.. _stubbing-multiple-calls:
Stubbing Multiple Calls
-----------------------
Another benefit of the stub mapping in Phake is that it allows you to very easily stub multiple calls to the same
method that use different parameters. In my shopping cart I have decided to add some functionality that will allow
me to easily add multiple products that are a part of a group to the shopping cart. To facilitate this I have decided
to create a new class called ``ItemGroup``. The ``ItemGroup`` object will be
constructed with an array of ``Items``. It will have a method on the class that will add all of
the items in the group to the given cart and then the total price of items in the cart will be returned.
It should be noted that earlier I decided to make a small change to the ``ShoppingCart::addItem()``
method to have it return the total price of items in the cart. I figured that this would be nice api level functionality
to make working with the system a little bit easier. I would like to take advantage of that change with this code.
Here's a stub of the functionality I am considering.
.. code-block:: php
/**
* A group of items that can be added to a cart all at the same time
*/
class ItemGroup
{
/**
* @param array $items an array of Item objects
*/
public function __construct(array $items)
{
}
/**
* @param ShoppingCart $cart
* @return money The new total value of the cart
*/
public function addItemsToCart(ShoppingCart $cart)
{
}
}
The next test I am going to write now is going to be focusing on this new ``ItemGroup::addItemsToCart()``
method. In my test's ``setUp()`` method I'll create a new instance of ``ItemGroup``
which will require one or more ``Item`` implementations. I'll use mocks for those. Then the actual
test case I am going to start with will be a test to assert that ``ItemGroup::addItemsToCart()``
returns the new shopping cart value. I already know that I am going to need to get this value by looking at the
last return value from calls to ``ShoppingCart::addItem()``. To allow for checking this I will mock
``ShoppingCart`` and create three stubs for ``ShoppingCart::addItem()``. Each
stub will be for a call with a different ``Item``.
.. code-block:: php
class ItemGroupTest extends PHPUnit_Framework_TestCase
{
private $itemGroup;
private $item1;
private $item2;
private $item3;
public function setUp()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
$this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3));
}
public function testAddItemsToCart()
{
$cart = Phake::mock('ShoppingCart');
Phake::when($cart)->addItem($this->item1)->thenReturn(10);
Phake::when($cart)->addItem($this->item2)->thenReturn(20);
Phake::when($cart)->addItem($this->item3)->thenReturn(30);
$totalCost = $this->itemGroup->addItemsToCart($cart);
$this->assertEquals(30, $totalCost);
}
}
In this example the ``ShoppingCart::addItem()`` method is being stubbed three times. Each time it
is being stubbed with a different parameter being passed to ``addItem()``. This a good example of
how parameters are also checked whenever Phake looks at a mock object's stub map for answers. The default behavior
of argument matching is again a loose equality check. Similar to how you would use the double equals operator in PHP.
The other options for argument matching are discussed further in :ref:`method-parameter-matchers-section`.
Stubbing Consecutive Calls
--------------------------
The previous test was a great example for how you can make multiple stubs for a single method however in reality it
is not the best way for that particular test to be written. What if the ``Item`` objects in an
``ItemGroup`` aren't stored in the order they were passed in? I am needlessly binding my test
to the order in which objects are stored. Phake provides the ability to map multiple answers to the same stub. This is
done simply by chaining the answers together. I could rewrite the test from the previous chapter to utilize this
feature of Phake.
.. code-block:: php
class ItemGroupTest extends PHPUnit_Framework_TestCase
{
private $itemGroup;
private $item1;
private $item2;
private $item3;
public function setUp()
{
$this->item1 = Phake::mock('Item');
$this->item2 = Phake::mock('Item');
$this->item3 = Phake::mock('Item');
$this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3));
}
public function testAddItemsToCart()
{
$cart = Phake::mock('ShoppingCart');
Phake::when($cart)->addItem(Phake::anyParameters())->thenReturn(10)
->thenReturn(20)
->thenReturn(30);
$totalCost = $this->itemGroup->addItemsToCart($cart);
$this->assertEquals(30, $totalCost);
}
}
You will notice a few of differences between this example and the example in :ref:`stubbing-multiple-calls`. The first
difference is that there is only one call to ``Phake::when()``. The second difference is that I have chained together three
calls to ``thenReturn()``. The third difference is instead of passing one of my mock Item
objects I have passed the result of the ``Phake::anyParameters()`` method. This is a special argument
matcher in Phake that essentially says match any call to the method regardless of the number of parameters or the
value of those parameters. You can learn more about ``Phake::anyParameters()`` in :ref:`wildcard-parameters`.
So, this single call to ``Phake::when()`` is saying: "Whenever a call to ``$cart->addItem()``
is made, regardless of the parameters, return 10 for the first call, 20 for the second call, and 30 for the third
call." If you are using consecutive call stubbing and you call the method more times than you have answers set, the
last answer will continue to be returned. In this example, if ``$cart->addItem()`` were called a fourth
time, then 30 would be returned again.
Stubbing Reference Parameters
-----------------------------
Occasionally you may run into code that utilizes reference parameters to provide additional output
from a method. This is not an uncommon thing to run into with legacy code. Phake provides a custom
parameter matcher (these are discussed further in :ref:`method-parameter-matchers-section`)
that allows you to set reference parameters. It can be accessed using ``Phake::setReference()``.
The only parameter to this matcher is the value you would like to set the reference parameter
to provided all other parameters match.
.. code-block:: php
interface IValidator
{
/**
* @parm array $data Data to validate
* @parm array &$errors contains all validation errors if the data is not valid
* @return boolean True when the data is valid
*/
public function validate(array $data, array &$errors);
}
class ValidationLogger implements IValidator
{
private $validator;
private $log;
public function __construct(IValidator $validator, Logger $log)
{
$this->validator = $validator;
$this->log = $log;
}
public function validate(array $data, array &$errors)
{
if (!$this->validator->validate($data, $errors))
{
foreach ($errors as $error)
{
$this->log->info("Validation Error: {$error}");
}
return FALSE;
}
return TRUE;
}
}
class ValidationLoggerTest extends PHPUnit_Framework_TestCase
{
public function testValidate()
{
//Mock the dependencies
$validator = Phake::mock('IValidator');
$log = Phake::mock('Logger');
$data = array('data1' => 'value');
$expectedErrors = array('data1 is not valid');
//Setup the stubs (Notice the Phake::setReference()
Phake::when($validator)->validate($data, Phake::setReference($expectedErrors))->thenReturn(FALSE);
//Instantiate the SUT
$validationLogger = new ValidationLogger($validator, $log);
//verify the validation is false and the message is logged
$errors = array();
$this->assertFalse($validationLogger->validate($data, $errors));
Phake::verify($log)->info('Validation Error: data1 is not valid');
}
}
In the example above, I am testing a new class I have created called ``ValidationLogger``.
It is a decorator for other implementations of ``IValidator`` that allows adding
logging to any other validator. The ``IValidator::validate()`` method will always
return an array of errors into the second parameter (a reference parameter) provided to the method.
These errors are what my logger is responsible for logging. So in order for my test to work properly,
I will need to be able to set that second parameter as a part of my stubbing call.
In the call to ``Phake::when($validator)->validate()`` I have passed a call to
``Phake::setReference()`` as the second parameter. This is causing the mock
implementation of ``IValidator`` to set ``$errors`` in
``ValidationLogger::validate()`` to the array specified by ``$expectedErrors``.
This allows me to quickly and easily validate that I am actually logging the errors returned back
in the reference parameter.
By default ``Phake::setReference()`` will always return true regardless of the
parameter initially passed in. If you would like to only set a reference parameter when that reference
parameter was passed in as a certain value you can use the ``when()`` modifier.
This takes a single parameter matcher as an argument. Below,
you will see that the test has been modified to call ``when()`` on the result
of `Phake::setReference()``. This modification will cause the reference parameter
to be set only if the $errors parameter passed to ``IValidator::validate()``
is initially passed as an empty array.
.. code-block:: php
class ValidationLoggerTest extends PHPUnit_Framework_TestCase
{
public function testValidate()
{
//Mock the dependencies
$validator = Phake::mock('IValidator');
$log = Phake::mock('Logger');
$data = array('data1' => 'value');
$expectedErrors = array('data1 is not valid');
//Setup the stubs (Notice the Phake::setReference()
Phake::when($validator)->validate($data, Phake::setReference($expectedErrors)->when(array())->thenReturn(FALSE);
//Instantiate the SUT
$validationLogger = new ValidationLogger($validator, $log);
//verify the validation is false and the message is logged
$errors = array();
$this->assertFalse($validationLogger->validate($data, $errors));
Phake::verify($log)->info('Validation Error: data1 is not valid');
}
}
Please note, when you are using ``Phake::setReference()`` you still must provide
an answer for the stub. If you use this function and your reference parameter is never changed,
that is generally the most common reason.
.. _partial-mocks:
Partial Mocks
-------------
When testing legacy code, if you find that the majority of the methods in the mock are using the ``thenCallParent()``
answer, you may find it easier to just use a partial mock in Phake. Phake partial mocks also allow you to call the
actual constructor of the class being mocked. They are created using ``Phake::partialMock()``. Like ``Phake::mock()``,
the first parameter is the name of the class that you are mocking. However, you can pass additional parameters that
will then be passed as the respective parameters to that class constructor. The other notable feature of a partial
mock in Phake is that its default answer is to pass the call through to the parent as if you were using
``thenCallParent()``.
Consider the following class that has a method that simply returns the value passed into the constructor.
.. code-block:: php
class MyClass
{
private $value;
public __construct($value)
{
$this->value = $value;
}
public function foo()
{
return $this->value;
}
}
Using ``Phake::partialMock()`` you can instantiate a mock object that will allow this object to function
as designed while still allowing verification as well as selective stubbing of certain calls.
Below is an example that shows the usage of ``Phake::partialMock()``.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testCallingParent()
{
$mock = Phake::partialMock('MyClass', 42);
$this->assertEquals(42, $mock->foo());
}
}
Again, partial mocks should not be used when you are testing new code. If you find yourself using them be sure to
inspect your design to make sure that the class you are creating a partial mock for is not doing too much.
Setting Default Stubs
---------------------
You can also change the default stubbing for mocks created with ``Phake::mock()``. This is done by using the second
parameter to ``Phake::mock()`` in conjunction with the ``Phake::ifUnstubbed()`` method. The second parameter to
``Phake::mock()`` is reserved for configuring the behavior of an individual mock. ``Phake::ifUnstubbed()`` allows you
to specify any of the matchers mentioned above as the default answer if any method invocation is not explicitly
stubbed. If this configuration directive is not provided then the method will return NULL by default. An example of
this can be seen below.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testDefaultStubs()
{
$mock = Phake::mock('MyClass', Phake::ifUnstubbed()->thenReturn(42));
$this->assertEquals(42, $mock->foo());
}
}
Stubbing Magic Methods
----------------------
Most magic methods can be stubbed using the method name just like you would any other method. The one exception to this
is the ``__call()`` method. This method is overwritten on each mock already to allow for the fluent api that Phake
utilizes. If you want to stub a particular invocation of ``__call()`` you can create a stub for the method you are
targetting in the first parameter to ``__call()``.
Consider the following class.
.. code-block:: php
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
You could stub an invocation of the ``__call()`` method through a userspace call to ``magicCall()`` with the following code.
.. code-block:: php
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
Phake::when($mock)->magicCall()->thenReturn(42);
$this->assertEquals(42, $mock->magicCall());
}
}
If for any reason you need to explicitly stub calls to ``__call()`` then you can use ``Phake::whenCallMethodWith()``.
The matchers passed to ``Phake::whenCallMethod()`` will be matched to the method name and array of arguments similar to
what you would expect to be passed to a ``__call()`` method. You can also use Phake::anyParameters() instead.
.. code-block:: php
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
Phake::whenCallMethodWith('magicCall', array())->isCalledOn($mock)->thenReturn(42);
$this->assertEquals(42, $mock->magicCall());
}
}

View File

@ -0,0 +1,278 @@
.. _method-verification-section:
*******************
Method Verification
*******************
The ``Phake::verify()`` method is used to assert that method calls have been
made on a mock object that you can create with ``Phake::mock()``.
``Phake::verify()`` accepts the mock object you want to verify calls against.
Mock objects in Phake can almost be viewed as a tape recorder. Any time the code you are testing
calls a method on an object you create with ``Phake::mock()`` it is going to
record the method that you called along with all of the parameters used to call that method. Then
``Phake::verify()`` will look at that recording and allow you to assert whether
or not a certain call was made.
.. code-block:: php
class PhakeTest1 extends PHPUnit_Framework_TestCase
{
public function testBasicVerify()
{
$mock = Phake::mock('MyClass');
$mock->foo();
Phake::verify($mock)->foo();
}
}
The ``Phake::verify()`` call here, verifies that the method ``foo()`` has been called once (and only once) with no
parameters on the object ``$mock``. A very important thing to note here that is a departure from most (if not all)
other PHP mocking frameworks is that you want to verify the method call AFTER the method call takes place. Other
mocking frameworks such as the one built into PHPUnit depend on you setting the expectations of what will get called
prior to running the system under test.
Phake strives to allow you to follow the four phases of a unit test as laid out in xUnit Test Patterns: setup,
exercise, verify, and teardown. The setup phase of a test using Phake for mocking will now include calls to
``Phake::mock()`` for each class you want to mock. The exercise portion of your code will remain the same. The verify
section of your code will include calls to ``Phake::verify()``. The exercise and teardown phases will remain unchanged.
Verifying Method Parameters
===========================
Verifying method parameters using Phake is very simple yet can be very flexible. There are a wealth of options for
matching parameters that are discussed later on in :ref:`method-parameter-matchers-section`.
Verifying Multiple Invocations
==============================
A common need for mock objects is the ability to have variable multiple invocations on that object. Phake allows you to
use ``Phake::verify()`` multiple times on the same object. A notable difference between Phake and PHPUnits mocking
framework is the ability to mock multiple invocations of the same method with no regard for call sequences. The PHPUnit
mocking test below would fail for this reason.
.. code-block:: php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = $this->getMock('PhakeTest_MockedClass');
$mock->expects($this->once())->method('fooWithArgument')
->with('foo');
$mock->expects($this->once())->method('fooWithArgument')
->with('bar');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
}
}
The reason this test fails is because by default PHPUnit only allows a single expectation per method. The way you can
fix this is by using the `at()` matcher. This allows you to specify the index of the invocation you want to match
again. So to make the test above work you would have to change it.
.. code-block:: php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = $this->getMock('PhakeTest_MockedClass');
//NOTICE this is now at() instead of once()
$mock->expects($this->at(0))->method('fooWithArgument')
->with('foo');
//NOTICE this is now at() instead of once()
$mock->expects($this->at(1))->method('fooWithArgument')
->with('bar');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
}
}
This test will now run as expected. There is still one small problem however and that is that you are now testing not
just the invocations but also the order of invocations. Many times the order in which two calls are made really do not
matter. If swapping the order of two method calls will not break your application then there is no reason to enforce
that code structure through a unit test. Unfortunately, you cannot have multiple invocations of a method in PHPUnit
without enforcing call order. In Phake these two notions of call order and multiple invocations are kept completely
distinct. Here is the same test written using Phake.
.. code-block:: php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
Phake::verify($mock)->fooWithArgument('foo');
Phake::verify($mock)->fooWithArgument('bar');
}
}
You can switch the calls around in this example as much as you like and the test will still pass. You can mock as many
different invocations of the same method as you need.
If you would like to verify the exact same parameters are used on a method multiple times (or they all match the same
constraints multiple times) then you can use the verification mode parameter of ``Phake::verify()``. The second
parameter to ``Phake::verify()`` allows you to specify how many times you expect that method to be called with matching
parameters. If no value is specified then the default of one is used. The other options are:
* ``Phake::times($n)`` Where ``$n`` equals the exact number of times you expect the method to be called.
* ``Phake::atLeast($n)`` Where ``$n`` is the minimum number of times you expect the method to be called.
* ``Phake::atMost($n)`` Where ``$n`` is the most number of times you would expect the method to be called.
* ``Phake::never()`` - Same as calling ``Phake::times(0)``.
Here is an example of this in action.
.. code-block:: php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('foo');
Phake::verify($mock, Phake::times(2))->fooWithArgument('foo');
}
}
Verifying Calls Happen in a Particular Order
============================================
Sometimes the desired behavior is that you verify calls happen in a particular order. Say there is a functional reason
for the two variants of ``fooWithArgument()`` to be called in the order of the original test. You can utilize
``Phake::inOrder()`` to ensure the order of your call invocations. ``Phake::inOrder()`` takes one or more arguments and
errors out in the event that one of the verified calls was invoked out of order. The calls dont have to be in exact
sequential order, there can be other calls in between, it just ensures the specified calls themselves are called in
order relative to each other. Below is an example Phake test that behaves similarly to the PHPUnit test that utilized
``at()``.
.. code-block:: php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testPHPUnitMock()
{
$mock = Phake::mock('PhakeTest_MockedClass');
$mock->fooWithArgument('foo');
$mock->fooWithArgument('bar');
Phake::inOrder(
Phake::verify($mock)->fooWithArgument('foo'),
Phake::verify($mock)->fooWithArgument('bar')
);
}
}
Verifying No Interaction with a Mock so Far
===========================================
Occasionally you may want to ensure that no interactions have occurred with a mock object. This can be done
by passing your mock object to ``Phake::verifyNoInteraction($mock)``. This will not prevent further interaction
with your mock, it will simply tell you whether or not any interaction up to that point has happened. You
can pass multiple arguments to this method to verify no interaction with multiple mock objects.
Verifying No Further Interaction with a Mock
============================================
There is a similar method to prevent any future interaction with a mock. This can be done by passing a mock
object to ``Phake::verifyNoFurtherInteraction($mock)``. You can pass multiple arguments to this method to
verify no further interaction occurs with multiple mock objects.
Verifying No Unverified Interaction with a Mock
============================================
By default any unverified calls to a mock are ignored. That is to say, if a call is made to `$mock->foo()` but
`Phake::verify($mock)->foo()` is never used, then no failures are thrown. If you want to be stricter and ensure that
all calls have been verified you can call `Phake::verifyNoOtherInteractions($mock)` at the end of your test. This will
check and make sure that all calls to your mock have been verified by one or more calls to Phake verify. This method
should only be used in those cases where you can clearly say that it is important that your test knows about all calls
on a particular object. One useful case for instance could be in testing a method that returns a filtered array.
.. code-block:: php
class FilterTest {
public function testFilteredList()
{
$filter = new MyFilter();
$list = Phake::Mock('MyList');
$filter->addEvenToList(array(1, 2, 3, 4, 5), $list);
Phake::verify($list)->push(2);
Phake::verify($list)->push(4);
Phake::verifyNoOtherInteractions($list);
}
}
Without `Phake::verifyNoOtherInteractions($list)` you would have to add additional verifications that `$list->push()`
was not called for the odd values in the list. This method should be used only when necessary. Using it in every test
is an anti-pattern that will lead to brittle tests.
Verifying Magic Methods
=======================
Most magic methods can be verified using the method name just like you would any other method. The one exception to this
is the ``__call()`` method. This method is overwritten on each mock already to allow for the fluent api that Phake
utilizes. If you want to verify a particular invocation of ``__call()`` you can verify the actual method call by
mocking the method passed in as the first parameter.
Consider the following class.
.. code-block:: php
class MagicClass
{
public function __call($method, $args)
{
return '__call';
}
}
You could mock an invocation of the `__call()` method through a userspace call to magicCall() with the following code.
.. code-block:: php
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
$mock->magicCall();
Phake::verify($mock)->magicCall();
}
}
If for any reason you need to explicitly verify calls to ``__call()`` then you can use ``Phake::verifyCallMethodWith()``.
.. code-block:: php
class MagicClassTest extends PHPUnit_Framework_TestCase
{
public function testMagicCall()
{
$mock = Phake::mock('MagicClass');
$mock->magicCall(42);
Phake::verifyCallMethodWith('magicCall', array(42))->isCalledOn($mock);
}
}

View File

@ -0,0 +1,116 @@
**********************
Mocking Static Methods
**********************
Phake can be used to verify as well as stub polymorphic calls to static methods. It is important to note that you
cannot verify or stub all static calls. In order for Phake to record or stub a method call, it needs to intercept the
call so that it can record it. Consider the following class
.. code-block:: php
class StaticCaller
{
public function callStaticMethod()
{
Foo::staticMethod();
}
}
You will not be able to stub or verify the call to Foo::staticMethod() because the call was made directly on the class.
This prevents Phake from seeing that the call was made. However, say you have an abstract class that has an abstract
static method.
.. code-block:: php
abstract class StaticFactory
{
protected static function factory()
{
// ...
}
public static function getInstance()
{
return static::factory();
}
}
In this case, because the ``static::`` keyword will cause the called class to be determined at runtime, you will be able
to verify and stub calls to StaticFactory::factory(). It is important to note that if self::factory() was called then
stubs and verifications would not work, because again the class is determined at compile time with the self:: keyword.
The key thing to remember with testing statics using Phake is that you can only test statics that leverage Late Static
Binding: http://www.php.net/manual/en/language.oop5.late-static-bindings.php
The key to testing static methods using Phake is that you need to create a "seam" for your static methods. If you are
not familiar with that term, a seam is a location where Phake is able to override and intercept calls to your code.
The typical seem for Phake is a parameter that allows you to pass your object. Typically you would pass a real object,
however during testing you pass in a mock object created by Phake. This is taking advantage of an instance seam.
Thankfully in php now you can do something along the lines of $myVar::myStatic() where if $myVar is a string it
resolves as you would think for a static method. The useful piece though is that if $myVar is an object, it will
resolve that object down to the class name and use that for the static.
So, the general idea here is that you can take code that is in class Foo:
.. code-block:: php
class Foo
{
public function doSomething()
{
// ... code that does stuff ...
Logger::logData();
}
}
which does not provide a seam for mocking Logger::logData() and provide that seem by changing it to:
.. code-block:: php
class Foo
{
public $logger = 'Logger';
public function doSomething()
{
// ... code that does stuff ...
$logger = $this->logger;
$logger::logData($data);
}
}
Now you can mock logData as follows:
.. code-block:: php
class FooTest
{
public function testDoSomething()
{
$foo = new Foo();
$foo->logger = Phake::mock('Logger');
$foo->doSomething();
Phake::verifyStatic($foo->logger)->logData(Phake::anyParameters());
}
}
Phake has alternative methods to handle interacting with static methods on your mock class. ``Phake::mock()`` is still
used to create the mock class, but the remaining interactions with static methods use more specialized methods. The
table below shows the Phake methods that have a separate counterpart for interacting with static calls.
+-----------------------------------+-----------------------------------------+
| Instance Method | Static Method |
+===================================+=========================================+
| ``Phake::when()`` | ``Phake::whenStatic()`` |
+-----------------------------------+-----------------------------------------+
| ``Phake::verify()`` | ``Phake::verifyStatic()`` |
+-----------------------------------+-----------------------------------------+
| ``Phake::verifyCallMethodWith()`` | ``Phake::verifyStaticCallMethodWith()`` |
+-----------------------------------+-----------------------------------------+
| ``Phake::whenCallMethodWith()`` | ``Phake::whenStaticCallMethodWith()`` |
+-----------------------------------+-----------------------------------------+
| ``Phake::reset()`` | ``Phake::resetStatic()`` |
+-----------------------------------+-----------------------------------------+
If you are using Phake to stub or verify static methods then you should call ``Phake::resetStaticInfo()`` in the
the ``tearDown()`` method. This is necessary to reset the stubs and call recorder for the static calls in the event
that the mock class gets re-used.

View File

@ -0,0 +1,217 @@
Creating Mocks
==============
The ``Phake::mock()`` method is how you create new test doubles in Phake. You pass in the class name of what you would
like to mock.
.. code-block:: php
$mock = Phake::mock('ClassToMock');
The ``$mock`` variable is now an instance of a generated class that inherits from ``ClassToMock`` with hooks that allow
you to force functions to return known values. By default, all methods on a mock object will return null. This behavior
can be overridden on a per method and even per parameter basis. This will be covered in depth in
:ref:`method-stubbing-section`.
The mock will also record all calls made to this class so that you can later verify that specific methods were called
with the proper parameters. This will be covered in depth in :ref:`method-verification-section`.
In addition to classes you can also mock interfaces directly. This is done in much the same way as a class name, you
simply pass the interface name as the first parameter to ``Phake::mock()``.
.. code-block:: php
$mock = Phake::mock('InterfaceToMock');
You can also pass an array of interface names to ``Phake::mock()`` that also contains up to 1 class name. This allows
for easier mocking of a dependency that is required to implement multiple interfaces.
.. code-block:: php
$mock = Phake::mock(array('Interface1', 'Interface2'));
Partial Mocks
-------------
When testing legacy code, you may find that a better default behavior for the methods is to actually call the original
method. This can be accomplished by stubbing each of the methods to return ``thenCallParent()``. You can learn more
about this in :ref:`then-call-parent`.
While this is certainly possible, you may find it easier to just use a partial mock in Phake. Phake partial mocks also
allow you to call the actual constructor of the class being mocked. They are created using ``Phake::partialMock()``.
Like ``Phake::mock()``, the first parameter is the name of the class that you are mocking. However, you can pass
additional parameters that will then be passed as the respective parameters to that class constructor. The other
notable feature of a partial mock in Phake is that its default answer is to pass the call through to the parent as if
you were using ``thenCallParent()``.
Consider the following class that has a method that simply returns the value passed into the constructor.
.. code-block:: php
class MyClass
{
private $value;
public __construct($value)
{
$this->value = $value;
}
public function foo()
{
return $this->value;
}
}
Using ``Phake::partialMock()`` you can instantiate a mock object that will allow this object to function
as designed while still allowing verification as well as selective stubbing of certain calls.
Below is an example that shows the usage of ``Phake::partialMock()``.
.. code-block:: php
class MyClassTest extends PHPUnit_Framework_TestCase
{
public function testCallingParent()
{
$mock = Phake::partialMock('MyClass', 42);
$this->assertEquals(42, $mock->foo());
}
}
Again, partial mocks should not be used when you are testing new code. If you find yourself using them be sure to
inspect your design to make sure that the class you are creating a partial mock for is not doing too much.
Calling Private and Protected Methods on Mocks
----------------------------------------------
Beginning in Phake 2.1 it is possible to invoke protected and private methods on your mocks using Phake. When you mock
a class, the mocked version will retain the same visibility on each of its functions as you would have had on your
original class. However, using ``Phake::makeVisible()`` and ``Phake::makeStaticsVisible()`` you can allow direct
invocation of instance methods and static methods accordingly. Both of these methods accept a mock object as its only
parameter and returns a proxy class that you can invoke the methods on. Method calls on these proxies will still
return whatever value was previously stubbed for that method call. So if you intend on the original method being called
and you aren't using :ref:`partial-mocks`, then you can just enable :ref:`calling-the-parent` for that method call using
the ``thenCallParent()`` answer. This is all discussed in greater depth in :ref:`method-stubbing` and :ref:`answers`.
.. code-block:: php
class MyClass
{
private function foo()
{
}
private static function bar()
{
}
}
Given the class above, you can invoke both private methods with the code below.
.. code-block:: php
$mock = Phake::mock('MyClass');
Phake::makeVisible($mock)->foo();
Phake::makeStaticVisible($mock)->bar();
As you can see above when using the static variant you still call the method as though it were an instance method. The
other thing to take note of is that there is no modification done on $mock itself. If you use ``Phake::makeVisible()``
you will only be able to make those private and protected calls off of the return of that method itself.
The best use case for this feature of Phake is if you have private or protected calls that are nested deep inside of
public methods. Generally speaking you would always just test from your class's public interface. However these large
legacy classes often require a significant amount of setup within fixtures to allow for calling those private and
protected methods. If you are only intending on refactoring the private and protected method then using
``Phake::makeVisible()`` removes the need for these complex fixtures.
Consider this really poor object oriented code. The cleanRowContent() function does some basic text processing such as
stripping html tags, cleaning up links, etc. It turns out that the original version of this method is written in a very
unperformant manner and I have been tasked with rewriting it.
.. code-block:: php
class MyReallyTerribleOldClass
{
public function __construct(Database $db)
{
//...
}
public function doWayTooMuch($data)
{
$result = $this->db->query($this->getQueryForData($data))
$rows = array();
while ($row = $this->db->fetch($result))
{
$rows[] = $this->cleanRowContent($row);
}
return $rows;
}
private function cleanRowContent($row)
{
//...
}
private function getQueryForData($data)
{
//...
}
}
If I was about to make changes to cleanRowContent and wanted to make sure I didn't break previous functionality, in order to
do so with the traditional fixture I would have to write a test similar to the following:
.. code-block:: php
class Test extends PHPUnit_Framework_TestCase
{
public function testProcessRow()
{
$dbRow = array('id' => '1', 'content' => 'Text to be processed with <b>tags stripped</b>');
$expectedValue = array(array('id' => 1', 'content' => 'Text to be processed with tags stripped');
$db = Phake::mock('Database');
$result = Phake::mock('DatabaseResult');
$oldClass = new MyReallyTerribleOldClass($db);
Phake::when($db)->query->thenReturn($result);
Phake::when($db)->fetch->thenReturn($dbRow)->thenReturn(null);
$data = $oldClass->doWayTooMuch(array());
$this->assertEquals($expectedValue, $data);
}
}
Using test helpers or PHPUnit data providers I could reuse this test to make sure I fully cover the various logic paths
and use cases for the cleanRowContent(). However this test is doing alot of work to just set up this scenario. Whenever
your test is hitting code not relevant to your test in increases the test's fragility. Here is how you could test the
same code using ``Phake::makeVisible()``.
.. code-block:: php
class Test extends PHPUnit_Framework_TestCase
{
public function testProcessRow()
{
$dbRow = array('id' => '1', 'content' => 'Text to be processed with <b>tags stripped</b>');
$expectedValue = array('id' => 1', 'content' => 'Text to be processed with tags stripped');
$oldClass = new Phake::partialMock('MyReallyTerribleOldClass');
$data = Phake::makeVisible($oldClass)->cleanRowContent($dbRow);
$this->assertEquals($expectedValue, $dbRow);
}
}
As you can see the test is significantly simpler. One final note, if you find yourself using this strategy on newly
written code, it could be a code smell indicitive of a class or public method doing too much. It is very reasonable
to argue that in my example, the ``cleanRowContent()`` method should be a class in and of itself or possibly a method
on a string manipulation type of class that my class then calls out to. This is a better design and also a much easier
to test design.

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Phake Test Suite">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,699 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Phake - PHP Test Doubles Framework
*
* Phake provides the functionality required for create mocks, stubs and spies. This is to allow
* a developer to isolate the code in a system under test (SUT) to provide better control of what
* code is being exercised in a particular test.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake
{
/**
* @var Phake_Facade
*/
private static $phake;
/**
* @var Phake_Client_IClient
*/
private static $client;
/**
* @var Phake_ClassGenerator_ILoader
*/
private static $loader;
/**
* @var Phake_Matchers_Factory
*/
private static $matchersFactory;
/**
* Constants identifying supported clients
*/
const CLIENT_DEFAULT = 'DEFAULT';
const CLIENT_PHPUNIT = 'PHPUNIT';
/**
* Returns a new mock object based on the given class name.
*
* @param string $className
* @param Phake_Stubber_IAnswerContainer $defaultAnswer
*
* @return mixed
*/
public static function mock($className, Phake_Stubber_IAnswerContainer $defaultAnswer = null)
{
if ($defaultAnswer === null) {
$answer = new Phake_Stubber_Answers_SmartDefaultAnswer();
} else {
$answer = $defaultAnswer->getAnswer();
}
return self::getPhake()->mock(
$className,
new Phake_ClassGenerator_MockClass(self::getMockLoader()),
new Phake_CallRecorder_Recorder(),
$answer
);
}
/**
* Returns a partial mock that is constructed with the given parameters
*
* Calls to this class will be recorded however they will still call the original functionality by default.
*
* @param string $className class name
* @param mixed $args,... the remaining arguments will be passed as constructor arguments
* @return Phake_IMock
*/
public static function partialMock($className, $args = null)
{
$args = array_slice(func_get_args(), 1);
$answer = new Phake_Stubber_Answers_ParentDelegate();
return self::getPhake()->mock(
$className,
new Phake_ClassGenerator_MockClass(self::getMockLoader()),
new Phake_CallRecorder_Recorder(),
$answer,
$args
);
}
/**
* For backwards compatibility
*
* @see Phake::partialMock()
* @param string $className class name
* @param mixed $args,... the remaining arguments will be passed as constructor arguments
* @return Phake_IMock
* @deprecated Please use Phake::partialMock() instead
*/
public static function partMock($className, $args = null)
{
$args = func_get_args();
return call_user_func_array('Phake::partialMock', $args);
}
/**
* Create a Phake_Matchers_Factory that we can re-use multiple times. Creating too many
* instances of this object is expensive.
*
* @return Phake_Matchers_Factory
*/
private static function getMatchersFactory ()
{
if (!self::$matchersFactory)
{
self::$matchersFactory = new Phake_Matchers_Factory();
}
return self::$matchersFactory;
}
/**
* Creates a new verifier for the given mock object.
*
* @param Phake_IMock $mock
* @param Phake_CallRecorder_IVerifierMode $mode
*
* @return Phake_Proxies_VerifierProxy
*/
public static function verify(Phake_IMock $mock, Phake_CallRecorder_IVerifierMode $mode = null)
{
if (is_null($mode)) {
$mode = self::times(1);
}
/* @var $info Phake_Mock_Info */
$info = Phake::getInfo($mock);
$verifier = new Phake_CallRecorder_Verifier($info->getCallRecorder(), $mock);
return new Phake_Proxies_VerifierProxy($verifier, self::getMatchersFactory(), $mode, self::getClient());
}
/**
* Creates a new verifier for the given mock object.
*
* @param Phake_IMock $mock
* @param Phake_CallRecorder_IVerifierMode $mode
*
* @return Phake_Proxies_VerifierProxy
*/
public static function verifyStatic(Phake_IMock $mock, Phake_CallRecorder_IVerifierMode $mode = null)
{
if (is_null($mode)) {
$mode = self::times(1);
}
/* @var $info Phake_Mock_Info */
$info = Phake::getInfo(get_class($mock));
$verifier = new Phake_CallRecorder_Verifier($info->getCallRecorder(), get_class($mock));
return new Phake_Proxies_VerifierProxy($verifier, self::getMatchersFactory(), $mode, self::getClient());
}
/**
* Creates a new verifier for verifying the magic __call method
*
* @param mixed ... A vararg containing the expected arguments for this call
*
* @return Phake_Proxies_CallVerifierProxy
*/
public static function verifyCallMethodWith()
{
$arguments = func_get_args();
$factory = self::getMatchersFactory();
return new Phake_Proxies_CallVerifierProxy($factory->createMatcherChain(
$arguments
), self::getClient(), false);
}
/**
* Creates a new verifier for verifying the magic __call method
*
* @param mixed ... A vararg containing the expected arguments for this call
*
* @return Phake_Proxies_CallVerifierProxy
*/
public static function verifyStaticCallMethodWith()
{
$arguments = func_get_args();
$factory = self::getMatchersFactory();
return new Phake_Proxies_CallVerifierProxy($factory->createMatcherChain(
$arguments
), self::getClient(), true);
}
/**
* Allows verification of methods in a particular order
*/
public static function inOrder()
{
$calls = func_get_args();
$orderVerifier = new Phake_CallRecorder_OrderVerifier();
if (!$orderVerifier->verifyCallsInOrder(self::pullPositionsFromCallInfos($calls))) {
$result = new Phake_CallRecorder_VerifierResult(false, array(), "Calls not made in order");
self::getClient()->processVerifierResult($result);
}
}
/**
* Allows for verifying that a mock object has no further calls made to it.
*
* @param Phake_IMock $mock
*/
public static function verifyNoFurtherInteraction(Phake_IMock $mock)
{
$mockFreezer = new Phake_Mock_Freezer();
foreach (func_get_args() as $mock) {
$mockFreezer->freeze(Phake::getInfo($mock), self::getClient());
$mockFreezer->freeze(Phake::getInfo(get_class($mock)), self::getClient());
}
}
/**
* Allows for verifying that no interaction occurred with a mock object
*
* @param Phake_IMock $mock
*/
public static function verifyNoInteraction(Phake_IMock $mock)
{
foreach (func_get_args() as $mock) {
$callRecorder = Phake::getInfo($mock)->getCallRecorder();
$verifier = new Phake_CallRecorder_Verifier($callRecorder, $mock);
self::getClient()->processVerifierResult($verifier->verifyNoCalls());
$sCallRecorder = Phake::getInfo(get_class($mock))->getCallRecorder();
$sVerifier = new Phake_CallRecorder_Verifier($sCallRecorder, get_class($mock));
self::getClient()->processVerifierResult($sVerifier->verifyNoCalls());
}
}
/**
* Allows for verifying that no other interaction occurred with a mock object outside of what has already been
* verified
*
* @param Phake_IMock $mock
*/
public static function verifyNoOtherInteractions(Phake_IMock $mock)
{
$callRecorder = Phake::getInfo($mock)->getCallRecorder();
$verifier = new Phake_CallRecorder_Verifier($callRecorder, $mock);
self::getClient()->processVerifierResult($verifier->verifyNoOtherCalls());
$sCallRecorder = Phake::getInfo(get_class($mock))->getCallRecorder();
$sVerifier = new Phake_CallRecorder_Verifier($sCallRecorder, get_class($mock));
self::getClient()->processVerifierResult($sVerifier->verifyNoOtherCalls());
}
/**
* Converts a bunch of call info objects to position objects.
*
* @param array $calls
*
* @return array
*/
private static function pullPositionsFromCallInfos(array $calls)
{
$transformed = array();
foreach ($calls as $callList) {
$transformedList = array();
foreach ($callList as $call) {
$transformedList[] = $call->getPosition();
}
$transformed[] = $transformedList;
}
return $transformed;
}
/**
* Returns a new stubber for the given mock object.
*
* @param Phake_IMock $mock
*
* @return Phake_Proxies_StubberProxy
*/
public static function when(Phake_IMock $mock)
{
return new Phake_Proxies_StubberProxy($mock, self::getMatchersFactory());
}
/**
* Returns a new static stubber for the given mock object.
*
* @param Phake_IMock $mock
*
* @return Phake_Proxies_StubberProxy
*/
public static function whenStatic(Phake_IMock $mock)
{
return new Phake_Proxies_StubberProxy(get_class($mock), self::getMatchersFactory());
}
/**
* Returns a new stubber specifically for the __call() method
*
* @param mixed ... A vararg containing the expected arguments for this call
*
* @return \Phake_Proxies_CallStubberProxy
*/
public static function whenCallMethodWith()
{
$arguments = func_get_args();
$factory = self::getMatchersFactory();
return new Phake_Proxies_CallStubberProxy($factory->createMatcherChain($arguments), false);
}
/**
* Returns a new stubber specifically for the __call() method
*
* @param mixed ... A vararg containing the expected arguments for this call
*
* @return \Phake_Proxies_CallStubberProxy
*/
public static function whenStaticCallMethodWith()
{
$arguments = func_get_args();
$factory = self::getMatchersFactory();
return new Phake_Proxies_CallStubberProxy($factory->createMatcherChain($arguments), true);
}
/**
* Resets all calls and stubs on the given mock object
*
* @param Phake_IMock $mock
*/
public static function reset(Phake_IMock $mock)
{
self::getInfo($mock)->resetInfo();
}
/**
* Resets all calls and stubs on the given mock object and return the original class name
*
* @param Phake_IMock $mock
* @return string $name
*/
public static function resetStatic(Phake_IMock $mock)
{
$info = self::getInfo(get_class($mock));
$info->resetInfo();
return $info->getName();
}
/**
* Resets all static calls, should be ran on tear downs
*/
public static function resetStaticInfo()
{
self::getPhake()->resetStaticInfo();
}
/**
* Provides methods for creating answers. Used in the api as a fluent way to set default stubs.
* @return Phake_Proxies_AnswerBinderProxy
*/
public static function ifUnstubbed()
{
$binder = new Phake_Stubber_SelfBindingAnswerBinder();
return new Phake_Proxies_AnswerBinderProxy($binder);
}
/**
* @param Phake_Facade $phake
*/
public static function setPhake(Phake_Facade $phake)
{
self::$phake = $phake;
}
/**
*
* @return Phake_Facade
*/
public static function getPhake()
{
if (empty(self::$phake)) {
self::setPhake(self::createPhake());
}
return self::$phake;
}
/**
* @return Phake_Facade
*/
public static function createPhake()
{
return new Phake_Facade(new Phake_Mock_InfoRegistry());
}
/**
* Returns an equals matcher for the given value.
*
* @param mixed $value
*
* @return Phake_Matchers_EqualsMatcher
*/
public static function equalTo($value)
{
return new Phake_Matchers_EqualsMatcher($value, new \SebastianBergmann\Comparator\Factory());
}
/**
* Returns a capturing matcher that will set the value of a given argument to given variable.
*
* @param mixed $value - Will be set to the value of the called argument.
*
* @return Phake_Matchers_ArgumentCaptor
*/
public static function capture(&$value)
{
return new Phake_Matchers_ArgumentCaptor($value);
}
/**
* Returns a capturing matcher that is bound to store ALL of its calls in the variable passed in.
*
* $value will initially be set to an empty array;
*
* @param mixed $value - Will be set to the value of the called argument.
*
* @return Phake_Matchers_ArgumentCaptor
*/
public static function captureAll(&$value)
{
$ignore = null;
$captor = new Phake_Matchers_ArgumentCaptor($ignore);
$captor->bindAllCapturedValues($value);
return $captor;
}
/**
* Returns a setter matcher that will set a reference parameter passed in as an argument to the
* given value.
*
* @param mixed $value - Will be written the reference parameter used by the calling method.
*
* @return Phake_Matchers_ReferenceSetter
*/
public static function setReference($value)
{
return new Phake_Matchers_ReferenceSetter($value);
}
/**
* Allows verifying an exact number of invocations.
*
* @param int $count
*
* @return Phake_CallRecorder_IVerifierMode
*/
public static function times($count)
{
return new Phake_CallRecorder_VerifierMode_Times((int)$count);
}
/**
* Allows verifying that there were no invocations. Alias of <code>times(0)</code>.
* @return Phake_CallRecorder_IVerifierMode
*/
public static function never()
{
return new Phake_CallRecorder_VerifierMode_Times(0);
}
/**
* Allows verifying at least <code>$count</code> invocations.
*
* @param int $count
*
* @return Phake_CallRecorder_IVerifierMode
*/
public static function atLeast($count)
{
return new Phake_CallRecorder_VerifierMode_AtLeast((int)$count);
}
/**
* Allows verifying at most <code>$count</code> invocations.
*
* @param int $count
*
* @return Phake_CallRecorder_IVerifierMode
*/
public static function atMost($count)
{
return new Phake_CallRecorder_VerifierMode_AtMost((int)$count);
}
/**
* Returns an any parameters matcher to allow matching all invocations of a particular method.
*
* @return Phake_Matchers_AnyParameters
*/
public static function anyParameters()
{
return new Phake_Matchers_AnyParameters();
}
/**
* Returns an any parameters matcher to allow matching all invocations of a particular method.
*
* @return Phake_Matchers_AnyParameters
*/
public static function ignoreRemaining()
{
return new Phake_Matchers_IgnoreRemainingMatcher();
}
/**
* Returns the client currently being used by Phake
*
* @return Phake_Client_IClient
*/
public static function getClient()
{
if (!isset(self::$client)) {
if (class_exists('PHPUnit_Framework_TestCase')) {
return self::$client = new Phake_Client_PHPUnit();
}
return self::$client = new Phake_Client_Default();
} else {
return self::$client;
}
}
/**
* Sets the client currently being used by Phake.
*
* Accepts either an instance of a Phake_Client_IClient object OR a string identifying such an object.
*
* @param Phake_Client_IClient|string $client
*/
public static function setClient($client)
{
if ($client instanceof Phake_Client_IClient) {
self::$client = $client;
} elseif ($client == self::CLIENT_PHPUNIT) {
self::$client = new Phake_Client_PHPUnit();
} else {
self::$client = new Phake_Client_Default();
}
}
public static function getMockLoader()
{
if (isset(self::$loader)) {
return self::$loader;
} else {
return new Phake_ClassGenerator_EvalLoader();
}
}
public static function setMockLoader(Phake_ClassGenerator_ILoader $loader)
{
self::$loader = $loader;
}
public static function initAnnotations($obj)
{
$initializer = new Phake_Annotation_MockInitializer();
$initializer->initialize($obj);
}
/**
* Used internally to validate mocks.
*
* @internal
* @param Phake_IMock|string $mock
* @throws InvalidArgumentException
*/
public static function assertValidMock($mock)
{
if ($mock instanceof Phake_IMock)
{
return;
}
if (is_string($mock) && class_exists($mock, false))
{
$reflClass = new ReflectionClass($mock);
if ($reflClass->implementsInterface('Phake_IMock'))
{
return;
}
}
throw new InvalidArgumentException("Received '" . (is_object($mock) ? get_class($mock) : $mock) . "' Expected an instance of Phake_IMock or the name of a class that implements Phake_IMock");
}
/**
* Used internally to standardize pulling mock names.
*
* @internal
* @param Phake_IMock|string $mock
* @throws InvalidArgumentException
* @return string
*/
public static function getName($mock)
{
static::assertValidMock($mock);
return $mock::__PHAKE_name;
}
/**
* Used internally to standardize pulling mock names.
*
* @internal
* @param Phake_IMock|string $mock
* @throws InvalidArgumentException
* @return Phake_Mock_Info
*/
public static function getInfo($mock)
{
static::assertValidMock($mock);
if ($mock instanceof Phake_IMock)
{
return isset($mock->__PHAKE_info) ? $mock->__PHAKE_info : null;
}
else
{
return $mock::$__PHAKE_staticInfo;
}
}
/**
* Increases allows calling private and protected instance methods on the given mock.
*
* @param Phake_IMock $mock
* @return Phake_Proxies_VisibilityProxy $mock
*/
public static function makeVisible(Phake_IMock $mock)
{
return new Phake_Proxies_VisibilityProxy($mock);
}
/**
* Increases allows calling private and protected static methods on the given mock.
*
* @param Phake_IMock $mock
* @return Phake_Proxies_VisibilityProxy $mock
*/
public static function makeStaticsVisible(Phake_IMock $mock)
{
return new Phake_Proxies_StaticVisibilityProxy($mock);
}
}

View File

@ -0,0 +1,98 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Initializes all properties of a given object that have the @Mock annotation.
*
* The class can be passed to the Mock annotation or it can also read the standard @var -annotation.
*
* In either case the fully qualified class name should be used. The use statements are not observed.
*/
class Phake_Annotation_MockInitializer
{
public function initialize($object)
{
$reflectionClass = new ReflectionClass($object);
$reader = new Phake_Annotation_Reader($reflectionClass);
if ($this->useDoctrineParser()) {
$parser = new \Doctrine\Common\Annotations\PhpParser();
}
$properties = $reader->getPropertiesWithAnnotation('Mock');
foreach ($properties as $property) {
$annotations = $reader->getPropertyAnnotations($property);
if ($annotations['Mock'] !== true) {
$mockedClass = $annotations['Mock'];
} else {
$mockedClass = $annotations['var'];
}
if (isset($parser)) {
// Ignore it if the class start with a backslash
if (substr($mockedClass, 0, 1) !== '\\') {
$useStatements = $parser->parseClass($reflectionClass);
$key = strtolower($mockedClass);
if (array_key_exists($key, $useStatements)) {
$mockedClass = $useStatements[$key];
}
}
}
$reflProp = new ReflectionProperty(get_class($object), $property);
$reflProp->setAccessible(true);
$reflProp->setValue($object, Phake::mock($mockedClass));
}
}
protected function useDoctrineParser()
{
return version_compare(PHP_VERSION, "5.3.3", ">=") && class_exists('Doctrine\Common\Annotations\PhpParser');
}
}

View File

@ -0,0 +1,121 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows reading annotations from various components
*/
class Phake_Annotation_Reader
{
/**
* @var ReflectionClass
*/
private $clazz;
/**
* @param ReflectionClass $clazz
*
* @throws InvalidArgumentException
*/
public function __construct(ReflectionClass $clazz)
{
$this->clazz = $clazz;
}
/**
* Returns an associative array containing a property's annotations and their values.
*
* @param string $property
*
* @return array
*/
public function getPropertyAnnotations($property)
{
$property = $this->clazz->getProperty($property);
return $this->readReflectionAnnotation($property);
}
/**
* Returns an array containing the names of all properties containing a particular annotation.
*
* @param string $annotation
*
* @return array
*/
public function getPropertiesWithAnnotation($annotation)
{
$properties = array();
foreach ($this->clazz->getProperties() as $property) {
$annotations = $this->getPropertyAnnotations($property->getName());
if (array_key_exists($annotation, $annotations)) {
$properties[] = $property->getName();
}
}
return $properties;
}
/**
* Returns all annotations for the given reflection object.
*
* @internal
*
* @param mixed $reflVar - must be an object that has the 'getDocComment' method.
*
* @return array
*/
private function readReflectionAnnotation($reflVar)
{
$comment = $reflVar->getDocComment();
$annotations = array();
foreach (explode("\n", $comment) as $line) {
if (preg_match('#^\s+\*\s*@(\w+)(?:\s+(.*))?\s*$#', $line, $matches)) {
$annotations[$matches[1]] = isset($matches[2]) ? $matches[2] : true;
}
}
return $annotations;
}
}

View File

@ -0,0 +1,118 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Represents a call. For use in storing with a call recorder.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_CallRecorder_Call
{
/**
* @var object
*/
private $object;
/**
* @var string
*/
private $method;
/**
* @var array
*/
private $arguments;
/**
* @param string|\Phake_IMock $context - The object the method was called on
* @param string $method - The method that was made
* @param array $arguments
*/
public function __construct($context, $method, array $arguments)
{
$this->object = $context;
$this->method = $method;
$this->arguments = $arguments;
}
/**
* @return object
*/
public function getObject()
{
return $this->object;
}
/**
* @return string
*/
public function getMethod()
{
return $this->method;
}
/**
* @return array
*/
public function getArguments()
{
return $this->arguments;
}
/**
* @return string
*/
public function __toString()
{
$converter = new Phake_String_Converter();
$arguments = array();
foreach ($this->arguments as $argument) {
$arguments[] = $converter->convertToString($argument);
}
$name = Phake::getName($this->object);
$access = is_string($this->object) ? '::' : '->';
return "{$name}{$access}{$this->method}(" . implode(', ', $arguments) . ")";
}
}

View File

@ -0,0 +1,140 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A call or set of calls that was expected
*/
class Phake_CallRecorder_CallExpectation
{
/**
* @var Phake_IMock
*/
private $object;
/**
* @var string
*/
private $method;
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $argumentMatcher;
/**
* @var Phake_CallRecorder_IVerifierMode
*/
private $verifierMode;
/**
* @param Phake_IMock|mixed $object
* @param string $method
* @param Phake_Matchers_IChainableArgumentMatcher $argumentMatcher
* @param Phake_CallRecorder_IVerifierMode $verificationMode
*/
public function __construct(
$object,
$method,
Phake_Matchers_IChainableArgumentMatcher $argumentMatcher = null,
Phake_CallRecorder_IVerifierMode $verificationMode
) {
$this->object = $object;
$this->method = $method;
$this->argumentMatcher = $argumentMatcher;
$this->verifierMode = $verificationMode;
}
/**
* @return Phake_IMock
*/
public function getObject()
{
return $this->object;
}
/**
* @return string
*/
public function getMethod()
{
return $this->method;
}
/**
* @return Phake_Matchers_IChainableArgumentMatcher
*/
public function getArgumentMatcher()
{
return $this->argumentMatcher;
}
/**
* @return Phake_CallRecorder_IVerifierMode
*/
public function getVerifierMode()
{
return $this->verifierMode;
}
public function __toString()
{
$arguments = array();
$argumentMatcher = $this->argumentMatcher;
while (!empty($argumentMatcher))
{
$arguments[] = $argumentMatcher->__toString();
$argumentMatcher = $argumentMatcher->getNextMatcher();
}
$name = Phake::getName($this->getObject());
$access = is_string($this->object) ? '::' : '->';
return "Expected {$name}{$access}{$this->getMethod()}(" . implode(
', ',
$arguments
) . ") to be called {$this->getVerifierMode()->__toString()}";
}
}

View File

@ -0,0 +1,85 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Aggregates various objects holding information about a particular call.
*/
class Phake_CallRecorder_CallInfo
{
/**
* @var Phake_CallRecorder_Call
*/
private $call;
/**
* @var Phake_CallRecorder_Position
*/
private $position;
/**
* @param Phake_CallRecorder_Call $call
* @param Phake_CallRecorder_Position $position
*/
public function __construct(Phake_CallRecorder_Call $call, Phake_CallRecorder_Position $position)
{
$this->call = $call;
$this->position = $position;
}
/**
* @return Phake_CallRecorder_Call
*/
public function getCall()
{
return $this->call;
}
/**
* @return Phake_CallRecorder_Position
*/
public function getPosition()
{
return $this->position;
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An api to process verification failures found by Phake_CallRecorder_Verifier
*
* @see Phake_CallRecorder_Verifier
*/
interface Phake_CallRecorder_IVerificationFailureHandler
{
public function verificationFailed(
$object,
$method,
array $argumentMatchers,
$mode,
$matches,
array $callsToMethod
);
}

View File

@ -0,0 +1,66 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows verifying that call invocations occurred some number of times.
*
* @author Brian Feaver <brian.feaver@gmail.com>
*/
interface Phake_CallRecorder_IVerifierMode
{
/**
* Verifies that the number of <code>$matchedCalls</code> matches the number of invocations expected.
*
* @param array $matchedCalls
*
* @return Phake_CallRecorder_VerifierMode_Result
*/
public function verify(array $matchedCalls);
/**
* Returns a human readable description of the verifier mode
* @return string
*/
public function __toString();
}

View File

@ -0,0 +1,80 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Verifies whether given positions are given in order.
*/
class Phake_CallRecorder_OrderVerifier
{
/**
* @param array $calls
*
* @return bool
*/
public function verifyCallsInOrder(array $calls)
{
$call1 = array_shift($calls);
$call2 = array_shift($call1);
while (count($calls)) {
$callList = array_shift($calls);
$callFound = false;
foreach ($callList as $call) {
/* @var $call Phake_CallRecorder_Position */
if ($call->thisIsAfter($call2)) {
$callFound = true;
$call2 = $call;
break;
}
}
if (!$callFound) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,74 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Provides information on the position of a given call.
*/
class Phake_CallRecorder_Position
{
/**
* @var int
*/
private $position;
/**
* @param int $position
*/
public function __construct($position)
{
$this->position = $position;
}
/**
* Determines if this call position is after the given position
*
* @param Phake_CallRecorder_Position $other
*
* @return boolean
*/
public function thisIsAfter(Phake_CallRecorder_Position $other)
{
return ($this->position > $other->position);
}
}

View File

@ -0,0 +1,143 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Records calls made to particular objects.
*
* It is assumed that calls will be recorded in the order that they are made.
*
* Provides methods to playback calls again in order.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_CallRecorder_Recorder
{
/**
* @var array
*/
private $calls = array();
/**
* @var array
*/
private $positions = array();
/**
* @var array
*/
private $unverifiedCalls = array();
/**
* @var int
*/
private static $lastPosition = 0;
/**
* Records that a given
*
* @param Phake_CallRecorder_Call $call
*/
public function recordCall(Phake_CallRecorder_Call $call)
{
$this->calls[] = $call;
$this->positions[spl_object_hash($call)] = new Phake_CallRecorder_Position(self::$lastPosition++);
$this->unverifiedCalls[spl_object_hash($call)] = $call;
}
/**
* Returns all calls recorded in the order they were recorded.
* @return array
*/
public function getAllCalls()
{
return $this->calls;
}
/**
* Removes all calls from the call recorder.
*
* Also removes all positions
*/
public function removeAllCalls()
{
$this->calls = array();
$this->positions = array();
}
/**
* Retrieves call info for a particular call
*
* @param Phake_CallRecorder_Call $call
*
* @return Phake_CallRecorder_CallInfo
*/
public function getCallInfo(Phake_CallRecorder_Call $call)
{
if (in_array($call, $this->calls, true)) {
return new Phake_CallRecorder_CallInfo($call, $this->positions[spl_object_hash($call)]);
} else {
return null;
}
}
/**
* Marks an individual call as being verified
*
* @param Phake_CallRecorder_Call $call
*/
public function markCallVerified(Phake_CallRecorder_Call $call)
{
unset($this->unverifiedCalls[spl_object_hash($call)]);
}
/**
* Returns all unverified calls from the recorder
*
* @return array
*/
public function getUnverifiedCalls()
{
return array_values($this->unverifiedCalls);
}
}

View File

@ -0,0 +1,185 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Can verify calls recorded into the given recorder.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_CallRecorder_Verifier
{
/**
* @var Phake_CallRecorder_Recorder
*/
protected $recorder;
/**
* @var Phake_IMock
*/
protected $obj;
/**
* @param Phake_CallRecorder_Recorder $recorder
* @param <type> $obj
*/
public function __construct(Phake_CallRecorder_Recorder $recorder, $obj)
{
$this->recorder = $recorder;
$this->obj = $obj;
}
/**
* Returns whether or not a call has been made in the associated call recorder.
*
* @todo Maybe rename this to findMatchedCalls?
*
* @param Phake_CallRecorder_CallExpectation $expectation
*
* @return Phake_CallRecorder_VerifierResult
*/
public function verifyCall(Phake_CallRecorder_CallExpectation $expectation)
{
$matcher = new Phake_Matchers_MethodMatcher($expectation->getMethod(), $expectation->getArgumentMatcher());
$calls = $this->recorder->getAllCalls();
$matchedCalls = array();
$methodNonMatched = array();
$obj_interactions = false;
foreach ($calls as $call) {
/* @var $call Phake_CallRecorder_Call */
if ($call->getObject() === $expectation->getObject()) {
$obj_interactions = true;
$args = $call->getArguments();
try
{
$matcher->assertMatches($call->getMethod(), $args);
$matchedCalls[] = $this->recorder->getCallInfo($call);
$this->recorder->markCallVerified($call);
}
catch (Phake_Exception_MethodMatcherException $e)
{
if ($call->getMethod() == $expectation->getMethod()) {
$message = $e->getMessage();
if (strlen($message))
{
$message = "\n{$message}";
}
$methodNonMatched[] = $call->__toString() . $message;
}
}
}
}
$verifierModeResult = $expectation->getVerifierMode()->verify($matchedCalls);
if (!$verifierModeResult->getVerified()) {
$additions = '';
if (!$obj_interactions) {
$additions .= ' In fact, there are no interactions with this mock.';
}
if (count($methodNonMatched)) {
$additions .= "\nOther Invocations:\n===\n " . implode("\n===\n ", str_replace("\n", "\n ", $methodNonMatched)) . "\n===";
}
return new Phake_CallRecorder_VerifierResult(
false,
array(),
$expectation->__toString() . ', ' . $verifierModeResult->getFailureDescription() . '.' . $additions
);
}
return new Phake_CallRecorder_VerifierResult(true, $matchedCalls);
}
public function verifyNoCalls()
{
$result = true;
$reportedCalls = array();
foreach ($this->recorder->getAllCalls() as $call) {
$result = false;
$reportedCalls[] = $call->__toString();
}
if ($result) {
return new Phake_CallRecorder_VerifierResult(true, array());
} else {
$desc = 'Expected no interaction with mock' . "\n"
. 'Invocations:' . "\n ";
return new Phake_CallRecorder_VerifierResult(false, array(), $desc . implode("\n ", $reportedCalls));
}
}
/**
* Ensures all calls for this verifier have actually been verified
*
* @return Phake_CallRecorder_VerifierResult
*/
public function verifyNoOtherCalls()
{
$result = true;
$reportedCalls = array();
foreach ($this->recorder->getUnverifiedCalls() as $call)
{
$result = false;
$reportedCalls[] = $call->__toString();
}
if ($result) {
return new Phake_CallRecorder_VerifierResult(true, array());
} else {
$desc = 'Expected no interaction with mock' . "\n"
. 'Invocations:' . "\n ";
return new Phake_CallRecorder_VerifierResult(false, array(), $desc . implode("\n ", $reportedCalls));
}
}
public function getObject()
{
return $this->obj;
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Verifier mode that checks that the number of matched items are equal to or greater than the expected amount.
* @author Brian Feaver <brian.feaver@gmail.com>
*/
class Phake_CallRecorder_VerifierMode_AtLeast implements Phake_CallRecorder_IVerifierMode
{
/**
* @var int
*/
private $times;
/**
* Constructs a verifier with the given <code>$times</code>.
*
* @param int $times
*/
public function __construct($times)
{
$this->times = $times;
}
/**
* Verifies that the number of <code>$matchedCalls</code> is equal to or greater than the
* value this object was instantiated with.
*
* @param array $matchedCalls
*
* @return boolean
*/
public function verify(array $matchedCalls)
{
$calledTimes = count($matchedCalls);
if ($calledTimes >= $this->times) {
return new Phake_CallRecorder_VerifierMode_Result(true, '');
} else {
return new Phake_CallRecorder_VerifierMode_Result(false, sprintf(
'actually called <%s> times',
count($matchedCalls)
));
}
}
public function __toString()
{
return "at least <{$this->times}> times";
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Verifier mode that checks that the number of matched items is less than or equal than the set amount.
* @author Brian Feaver <brian.feaver@gmail.com>
*/
class Phake_CallRecorder_VerifierMode_AtMost implements Phake_CallRecorder_IVerifierMode
{
/**
* @var int
*/
private $times;
/**
* Constructs a verifier with the given <code>$times</code>.
*
* @param int $times
*/
public function __construct($times)
{
$this->times = $times;
}
/**
* Verifies that the number of <code>$matchedCalls</code> is less than or equal to the
* value this object was instantiated with.
*
* @param array $matchedCalls
*
* @return boolean
*/
public function verify(array $matchedCalls)
{
$calledTimes = count($matchedCalls);
if ($calledTimes <= $this->times) {
return new Phake_CallRecorder_VerifierMode_Result(true, '');
} else {
return new Phake_CallRecorder_VerifierMode_Result(false, sprintf(
'actually called <%s> times',
count($matchedCalls)
));
}
}
public function __toString()
{
return "at most <{$this->times}> times";
}
}

View File

@ -0,0 +1,67 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
class Phake_CallRecorder_VerifierMode_Result
{
private $verified;
private $failureDescription;
function __construct($verified, $failureDescription)
{
$this->verified = $verified;
$this->failureDescription = $failureDescription;
}
public function getVerified()
{
return $this->verified;
}
public function getFailureDescription()
{
return $this->failureDescription;
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Verifier mode that checks that the number of matched items are exactly equal
* to the expected amount.
* @author Brian Feaver <brian.feaver@gmail.com>
*/
class Phake_CallRecorder_VerifierMode_Times implements Phake_CallRecorder_IVerifierMode
{
/**
* @var int
*/
private $times;
/**
* Constructs a Times verifier with the given <code>$times</code>.
*
* @param int $times
*/
public function __construct($times)
{
$this->times = $times;
}
/**
* Verifies that the number of <code>$matchedCalls</code> is equal to the
* value this object was instantiated with.
*
* @param array $matchedCalls
*
* @return boolean
*/
public function verify(array $matchedCalls)
{
$calledTimes = count($matchedCalls);
if ($calledTimes == $this->times) {
return new Phake_CallRecorder_VerifierMode_Result(true, '');
} else {
return new Phake_CallRecorder_VerifierMode_Result(false, sprintf(
'actually called <%s> times',
count($matchedCalls)
));
}
}
public function __toString()
{
return "exactly <{$this->times}> times";
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A value object containing the results of a run of verifyCall()
*/
class Phake_CallRecorder_VerifierResult
{
private $verified;
private $matchedCalls;
private $failureDescription;
/**
* @param boolean $verified
* @param array $matchedCalls
* @param string $failureDescription
*/
function __construct($verified, array $matchedCalls, $failureDescription = '')
{
$this->verified = $verified;
$this->matchedCalls = $matchedCalls;
$this->failureDescription = $failureDescription;
}
/**
* @return boolean
*/
public function getVerified()
{
return $this->verified;
}
/**
* @return array
*/
public function getMatchedCalls()
{
return $this->matchedCalls;
}
/**
* @return string
*/
public function getFailureDescription()
{
return $this->failureDescription;
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Loads classes into the system via the eval method
*/
class Phake_ClassGenerator_EvalLoader implements Phake_ClassGenerator_ILoader
{
/**
* @param string $className
* @param string $classDef
*
* @return void
*/
public function loadClassByString($className, $classDef)
{
eval($classDef);
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Saves the files into a store directory with a file name the same as the class and then includes that file.
*/
class Phake_ClassGenerator_FileLoader implements Phake_ClassGenerator_ILoader
{
private $dir;
/**
* @param string $dir
*/
public function __construct($dir)
{
$this->dir = $dir;
}
/**
* @param string $className
* @param string $classDef
*
* @return void
*/
public function loadClassByString($className, $classDef)
{
$file = rtrim($this->dir, '/') . '/' . $className . '.php';
file_put_contents($file, "<?php \n" . $classDef);
require_once($file);
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Loads classes into the system.
*/
interface Phake_ClassGenerator_ILoader
{
/**
* @param string $className
* @param string $classDef
*
* @return void
*/
public function loadClassByString($className, $classDef);
}

View File

@ -0,0 +1,71 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Records calls to a mock object's call recorder.
*/
class Phake_ClassGenerator_InvocationHandler_CallRecorder implements Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @var Phake_CallRecorder_Recorder
*/
private $callRecorder;
/**
* @param Phake_CallRecorder_Recorder $callRecorder
*/
public function __construct(Phake_CallRecorder_Recorder $callRecorder)
{
$this->callRecorder = $callRecorder;
}
public function invoke($mock, $method, array $arguments, array &$argumentReference)
{
$this->callRecorder->recordCall(
new Phake_CallRecorder_Call($mock, $method, $arguments)
);
}
}

View File

@ -0,0 +1,73 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A composite invocation handler
*/
class Phake_ClassGenerator_InvocationHandler_Composite implements Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @var array
*/
private $handlers;
/**
* @param array $handlers
*/
public function __construct(array $handlers)
{
$this->handlers = $handlers;
}
public function invoke($mock, $method, array $arguments, array &$argumentReference)
{
foreach ($this->handlers as $handler) {
$result = $handler->invoke($mock, $method, $arguments, $argumentReference);
}
return $result;
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Tests a mock to see if it is frozen.
*/
class Phake_ClassGenerator_InvocationHandler_FrozenObjectCheck implements Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @var Phake_Mock_Info
*/
private $mockInfo;
/**
* @param Phake_Mock_Info $mockInfo
*/
public function __construct(Phake_Mock_Info $mockInfo)
{
$this->mockInfo = $mockInfo;
}
public function invoke($mock, $method, array $arguments, array &$argumentReference)
{
if ($this->mockInfo->isObjectFrozen()) {
$result = new Phake_CallRecorder_VerifierResult(false, array(), 'This object has been frozen.');
Phake::getClient()->processVerifierResult($result);
}
}
}

View File

@ -0,0 +1,61 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An interface for invocation handlers.
*
* Invocation handlers are used to provide various functionality in reaction to a method invocation on a mock object.
*/
interface Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @param Phake_IMock|string $mock
* @param $method
* @param array $arguments
* @param array $argumentReference
* @return mixed
*/
public function invoke($mock, $method, array $arguments, array &$argumentReference);
}

View File

@ -0,0 +1,75 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Records calls to a mock object's call recorder for the magic __call method.
*
* If the invocation isn't of __call...does nothing.
*/
class Phake_ClassGenerator_InvocationHandler_MagicCallRecorder implements Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @var Phake_CallRecorder_Recorder
*/
private $callRecorder;
/**
* @param Phake_CallRecorder_Recorder $callRecorder
*/
public function __construct(Phake_CallRecorder_Recorder $callRecorder)
{
$this->callRecorder = $callRecorder;
}
public function invoke($mock, $method, array $arguments, array &$argumentReference)
{
if ($method == '__call' || $method == '__callStatic') {
$this->callRecorder->recordCall(
new Phake_CallRecorder_Call($mock, $arguments[0], $arguments[1])
);
}
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Records calls to a mock object's call recorder.
*/
class Phake_ClassGenerator_InvocationHandler_StubCaller implements Phake_ClassGenerator_InvocationHandler_IInvocationHandler
{
/**
* @var Phake_Stubber_StubMapper
*/
private $stubMapper;
/**
* @var Phake_Stubber_IAnswer
*/
private $defaultAnswer;
/**
* @param Phake_Stubber_StubMapper $stubMapper
* @param Phake_Stubber_IAnswer $defaultAnswer
*/
public function __construct(Phake_Stubber_StubMapper $stubMapper, Phake_Stubber_IAnswer $defaultAnswer)
{
$this->stubMapper = $stubMapper;
$this->defaultAnswer = $defaultAnswer;
}
public function invoke($mock, $method, array $arguments, array &$argumentReference)
{
$stub = null;
if ($method == '__call' || $method == '__callStatic') {
$stub = $this->stubMapper->getStubByCall($arguments[0], $argumentReference[1]);
}
if ($stub === null) {
$stub = $this->stubMapper->getStubByCall($method, $argumentReference);
}
if ($stub === null) {
$answer = $this->defaultAnswer;
} else {
$answer = $stub->getAnswer();
}
return $answer;
}
}

View File

@ -0,0 +1,657 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Creates and executes the code necessary to create a mock class.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_ClassGenerator_MockClass
{
private static $unsafeClasses = array('Memcached');
/**
* @var \Phake_ClassGenerator_ILoader
*/
private $loader;
private $reservedWords = array(
'abstract' => 'abstract',
'and' => 'and',
'array' => 'array',
'as' => 'as',
'break' => 'break',
'case' => 'case',
'catch' => 'catch',
'class' => 'class',
'clone' => 'clone',
'const' => 'const',
'continue' => 'continue',
'declare' => 'declare',
'default' => 'default',
'do' => 'do',
'else' => 'else',
'elseif' => 'elseif',
'enddeclare' => 'enddeclare',
'endfor' => 'endfor',
'endforeach' => 'endforeach',
'endif' => 'endif',
'endswitch' => 'endswitch',
'endwhile' => 'endwhile',
'extends' => 'extends',
'final' => 'final',
'for' => 'for',
'foreach' => 'foreach',
'function' => 'function',
'global' => 'global',
'goto' => 'goto',
'if' => 'if',
'implements' => 'implements',
'interface' => 'interface',
'instanceof' => 'instanceof',
'namespace' => 'namespace',
'new' => 'new',
'or' => 'or',
'private' => 'private',
'protected' => 'protected',
'public' => 'public',
'static' => 'static',
'switch' => 'switch',
'throw' => 'throw',
'try' => 'try',
'use' => 'use',
'var' => 'var',
'while' => 'while',
'xor' => 'xor',
'die' => 'die',
'echo' => 'echo',
'empty' => 'empty',
'exit' => 'exit',
'eval' => 'eval',
'include' => 'include',
'include_once' => 'include_once',
'isset' => 'isset',
'list' => 'list',
'require' => 'require',
'require_once' => 'require_once',
'return' => 'return',
'print' => 'print',
'unset' => 'unset',
'__halt_compiler' => '__halt_compiler'
);
/**
* @param Phake_ClassGenerator_ILoader $loader
*/
public function __construct(Phake_ClassGenerator_ILoader $loader = null)
{
if (empty($loader)) {
$loader = new Phake_ClassGenerator_EvalLoader();
}
$this->loader = $loader;
}
/**
* Generates a new class with the given class name
*
* @param string $newClassName - The name of the new class
* @param string $mockedClassName - The name of the class being mocked
* @param Phake_Mock_InfoRegistry $infoRegistry
* @return NULL
*/
public function generate($newClassName, $mockedClassName, Phake_Mock_InfoRegistry $infoRegistry)
{
$extends = '';
$implements = '';
$interfaces = array();
$parent = null;
$constructor = '';
$mockedClassNames = (array)$mockedClassName;
$mockedClasses = array();
foreach ($mockedClassNames as $mockedClassName)
{
$mockedClass = new ReflectionClass($mockedClassName);
$mockedClasses[] = $mockedClass;
if (!$mockedClass->isInterface()) {
if (!empty($parent))
{
throw new RuntimeException("You cannot use two classes in the same mock: {$parent->getName()}, {$mockedClass->getName()}. Use interfaces instead.");
}
$parent = $mockedClass;
} else {
if ($mockedClass->implementsInterface('Traversable') &&
!$mockedClass->implementsInterface('Iterator') &&
!$mockedClass->implementsInterface('IteratorAggregate')
) {
$interfaces[] = new ReflectionClass('Iterator');
if ($mockedClass->getName() != 'Traversable') {
$interfaces[] = $mockedClass;
}
}
else
{
$interfaces[] = $mockedClass;
}
}
}
$interfaces = array_unique($interfaces);
if (!empty($parent))
{
$extends = "extends {$parent->getName()}";
}
$interfaceNames = array_map(function (ReflectionClass $c) { return $c->getName(); }, $interfaces);
if(($key = array_search('Phake_IMock', $interfaceNames)) !== false) {
unset($interfaceNames[$key]);
}
if (!empty($interfaceNames))
{
$implements = ', ' . implode(',', $interfaceNames);
}
if (empty($parent))
{
$mockedClass = array_shift($interfaces);
}
else
{
$mockedClass = $parent;
}
$classDef = "
class {$newClassName} {$extends}
implements Phake_IMock {$implements}
{
public \$__PHAKE_info;
public static \$__PHAKE_staticInfo;
const __PHAKE_name = '{$mockedClassName}';
public \$__PHAKE_constructorArgs;
{$constructor}
/**
* @return void
*/
public function __destruct() {}
{$this->generateSafeConstructorOverride($mockedClasses)}
{$this->generateMockedMethods($mockedClass, $interfaces)}
}
";
$this->loadClass($newClassName, $mockedClassName, $classDef);
$newClassName::$__PHAKE_staticInfo = $this->createMockInfo($mockedClassName, new Phake_CallRecorder_Recorder(), new Phake_Stubber_StubMapper(), new Phake_Stubber_Answers_NoAnswer());
$infoRegistry->addInfo($newClassName::$__PHAKE_staticInfo);
}
private function loadClass($newClassName, $mockedClassName, $classDef)
{
$isUnsafe = in_array($mockedClassName, self::$unsafeClasses);
$oldErrorReporting = ini_get('error_reporting');
if ($isUnsafe)
{
error_reporting($oldErrorReporting & ~E_STRICT);
}
$this->loader->loadClassByString($newClassName, $classDef);
if ($isUnsafe)
{
error_reporting($oldErrorReporting);
}
}
/**
* Instantiates a new instance of the given mocked class, and configures Phake data structures on said object.
*
* @param string $newClassName
* @param Phake_CallRecorder_Recorder $recorder
* @param Phake_Stubber_StubMapper $mapper
* @param Phake_Stubber_IAnswer $defaultAnswer
* @param array $constructorArgs
*
* @return Phake_IMock of type $newClassName
*/
public function instantiate(
$newClassName,
Phake_CallRecorder_Recorder $recorder,
Phake_Stubber_StubMapper $mapper,
Phake_Stubber_IAnswer $defaultAnswer,
array $constructorArgs = null
) {
$mockObject = $this->instanciateMockObject($newClassName);
$mockObject->__PHAKE_info = $this->createMockInfo($newClassName::__PHAKE_name, $recorder, $mapper, $defaultAnswer);
$mockObject->__PHAKE_constructorArgs = $constructorArgs;
if (null !== $constructorArgs && method_exists($mockObject, '__construct')) {
call_user_func_array(array($mockObject, '__construct'), $constructorArgs);
}
return $mockObject;
}
/**
* Instantiates a new instance of the given mocked class.
*
* @param $newClassName
* @return object
*/
protected function instanciateMockObject ($newClassName) {
$reflClass = new ReflectionClass($newClassName);
$constructor = $reflClass->getConstructor();
if ($constructor == null || ($constructor->class == $newClassName && $constructor->getNumberOfParameters() == 0)) {
return new $newClassName;
}
if (method_exists($reflClass, "newInstanceWithoutConstructor")) {
try {
return $reflClass->newInstanceWithoutConstructor();
} catch (ReflectionException $ignore) {
/* Failed to create object, the class might be final. */
}
}
if (!is_subclass_of($newClassName, "Serializable")) {
/* Try to unserialize, this skips the constructor */
return unserialize(sprintf('O:%d:"%s":0:{}', strlen($newClassName), $newClassName));
}
/* Object implements custom unserialization */
return unserialize(sprintf('C:%d:"%s":0:{}', strlen($newClassName), $newClassName));
}
/**
* Generate mock implementations of all public and protected methods in the mocked class.
*
* @param ReflectionClass $mockedClass
* @param ReflectionClass[] $mockedInterfaces
*
* @return string
*/
protected function generateMockedMethods(ReflectionClass $mockedClass, array $mockedInterfaces = array(), &$implementedMethods = array())
{
$methodDefs = '';
$filter = ReflectionMethod::IS_ABSTRACT | ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PUBLIC | ~ReflectionMethod::IS_FINAL;
if (empty($implementedMethods))
{
$implementedMethods = $this->reservedWords;
}
foreach ($mockedClass->getMethods($filter) as $method) {
$methodName = $method->getName();
if (!$method->isConstructor() && !$method->isDestructor() && !$method->isFinal()
&& !isset($implementedMethods[$methodName])
) {
$implementedMethods[$methodName] = $methodName;
$methodDefs .= $this->implementMethod($method, $method->isStatic()) . "\n";
}
}
foreach ($mockedInterfaces as $interface) {
$methodDefs .= $this->generateMockedMethods($interface, array(), $implementedMethods);
}
return $methodDefs;
}
private function isConstructorDefinedInInterface(ReflectionClass $mockedClass)
{
$constructor = $mockedClass->getConstructor();
if (empty($constructor) && $mockedClass->hasMethod('__construct'))
{
$constructor = $mockedClass->getMethod('__construct');
}
if (empty($constructor))
{
return false;
}
$reflectionClass = $constructor->getDeclaringClass();
if ($reflectionClass->isInterface())
{
return true;
}
/* @var ReflectionClass $interface */
foreach ($reflectionClass->getInterfaces() as $interface)
{
if ($interface->getConstructor() !== null || $interface->hasMethod('__construct'))
{
return true;
}
}
$parent = $reflectionClass->getParentClass();
if (!empty($parent))
{
return $this->isConstructorDefinedInInterface($parent);
}
else
{
return false;
}
}
private function isConstructorDefinedAndFinal(ReflectionClass $mockedClass)
{
$constructor = $mockedClass->getConstructor();
if (!empty($constructor) && $constructor->isFinal()) {
return true;
}
return false;
}
private function generateSafeConstructorOverride(array $mockedClasses)
{
$overrideConstructor = true;
foreach ($mockedClasses as $class)
{
$overrideConstructor = $overrideConstructor
&& !$this->isConstructorDefinedAndFinal($class)
&& !$this->isConstructorDefinedInInterface($class);
if (!$class->isInterface())
{
$realClass = $class;
}
}
if ($overrideConstructor && !empty($realClass))
{
$constructorDef = "
public function __construct()
{
{$this->getConstructorChaining($realClass)}
}
";
return $constructorDef;
}
else
{
return '';
}
}
/**
* Creates the constructor implementation
*
* @param ReflectionClass $originalClass
* @return string
*/
protected function getConstructorChaining(ReflectionClass $originalClass)
{
return $originalClass->hasMethod('__construct') ? "
if (is_array(\$this->__PHAKE_constructorArgs))
{
call_user_func_array(array(\$this, 'parent::__construct'), \$this->__PHAKE_constructorArgs);
\$this->__PHAKE_constructorArgs = null;
}
" : "";
}
/**
* Creates the implementation of a single method
*
* @param ReflectionMethod $method
*
* @return string
*/
protected function implementMethod(ReflectionMethod $method, $static = false)
{
$modifiers = implode(
' ',
Reflection::getModifierNames($method->getModifiers() & ~ReflectionMethod::IS_ABSTRACT)
);
$reference = $method->returnsReference() ? '&' : '';
if ($static)
{
$context = '__CLASS__';
}
else
{
$context = '$this';
}
$returnHint = '';
$nullReturn = 'null';
$resultReturn = '$__PHAKE_result';
if (method_exists($method, 'hasReturnType') && $method->hasReturnType())
{
$returnType = $method->getReturnType();
$returnHint = ' : ' . $returnType;
if ($returnType == 'void')
{
$nullReturn = '';
$resultReturn = '';
}
}
$docComment = $method->getDocComment() ?: '';
$methodDef = "
{$docComment}
{$modifiers} function {$reference}{$method->getName()}({$this->generateMethodParameters($method)}){$returnHint}
{
\$__PHAKE_args = array();
{$this->copyMethodParameters($method)}
\$__PHAKE_info = Phake::getInfo({$context});
if (\$__PHAKE_info === null) {
return {$nullReturn};
}
\$__PHAKE_funcArgs = func_get_args();
\$__PHAKE_answer = \$__PHAKE_info->getHandlerChain()->invoke({$context}, '{$method->getName()}', \$__PHAKE_funcArgs, \$__PHAKE_args);
\$__PHAKE_callback = \$__PHAKE_answer->getAnswerCallback({$context}, '{$method->getName()}');
if (\$__PHAKE_callback instanceof Phake_Stubber_Answers_ParentDelegateCallback)
{
\$__PHAKE_result = \$__PHAKE_callback(\$__PHAKE_args);
}
else
{
\$__PHAKE_result = call_user_func_array(\$__PHAKE_callback, \$__PHAKE_args);
}
\$__PHAKE_answer->processAnswer(\$__PHAKE_result);
return {$resultReturn};
}
";
return $methodDef;
}
/**
* Generates the code for all the parameters of a given method.
*
* @param ReflectionMethod $method
*
* @return string
*/
protected function generateMethodParameters(ReflectionMethod $method)
{
$parameters = array();
foreach ($method->getParameters() as $parameter) {
$parameters[] = $this->implementParameter($parameter);
}
return implode(', ', $parameters);
}
/**
* Generates the code for all the parameters of a given method.
*
* @param ReflectionMethod $method
*
* @return string
*/
protected function copyMethodParameters(ReflectionMethod $method)
{
$copies = "\$funcGetArgs = func_get_args();\n\t\t\$__PHAKE_numArgs = count(\$funcGetArgs);\n\t\t";
$variadicParameter = false;
$parameterCount = count($method->getParameters());
foreach ($method->getParameters() as $parameter) {
$pos = $parameter->getPosition();
if (method_exists($parameter, 'isVariadic') && $parameter->isVariadic()) {
$parameterCount--;
$variadicParameter = $parameter->getName();
break;
}
else {
$copies .= "if ({$pos} < \$__PHAKE_numArgs) \$__PHAKE_args[] =& \${$parameter->getName()};\n\t\t";
}
}
if ($variadicParameter)
{
$copies .= "for (\$__PHAKE_i = " . $parameterCount . "; \$__PHAKE_i < \$__PHAKE_numArgs; \$__PHAKE_i++) \$__PHAKE_args[] =& \${$variadicParameter}[\$__PHAKE_i - $parameterCount];\n\t\t";
}
else
{
$copies .= "for (\$__PHAKE_i = " . $parameterCount . "; \$__PHAKE_i < \$__PHAKE_numArgs; \$__PHAKE_i++) \$__PHAKE_args[] = func_get_arg(\$__PHAKE_i);\n\t\t";
}
return $copies;
}
/**
* Generates the code for an individual method parameter.
*
* @param ReflectionParameter $parameter
*
* @return string
*/
protected function implementParameter(ReflectionParameter $parameter)
{
$default = '';
$type = '';
try
{
if ($parameter->isArray()) {
$type = 'array ';
} elseif (method_exists($parameter, 'isCallable') && $parameter->isCallable()) {
$type = 'callable ';
} elseif ($parameter->getClass() !== null) {
$type = $parameter->getClass()->getName() . ' ';
} elseif (method_exists($parameter, 'hasType') && $parameter->hasType())
{
$type = $parameter->getType() . ' ';
}
}
catch (ReflectionException $e)
{
//HVVM is throwing an exception when pulling class name when said class does not exist
if (!defined('HHVM_VERSION'))
{
throw $e;
}
}
$variadic = '';
if ($parameter->isDefaultValueAvailable()) {
$default = ' = ' . var_export($parameter->getDefaultValue(), true);
} elseif (method_exists($parameter, 'isVariadic') && $parameter->isVariadic()) {
$variadic = '...';
} elseif ($parameter->isOptional()) {
$default = ' = null';
}
return $type . ($parameter->isPassedByReference() ? '&' : '') . $variadic . '$' . $parameter->getName() . $default;
}
/**
* @param $newClassName
* @param Phake_CallRecorder_Recorder $recorder
* @param Phake_Stubber_StubMapper $mapper
* @param Phake_Stubber_IAnswer $defaultAnswer
* @return Phake_Mock_Info
*/
private function createMockInfo(
$className,
Phake_CallRecorder_Recorder $recorder,
Phake_Stubber_StubMapper $mapper,
Phake_Stubber_IAnswer $defaultAnswer
) {
$info = new Phake_Mock_Info($className, $recorder, $mapper, $defaultAnswer);
$info->setHandlerChain(
new Phake_ClassGenerator_InvocationHandler_Composite(array(
new Phake_ClassGenerator_InvocationHandler_FrozenObjectCheck($info),
new Phake_ClassGenerator_InvocationHandler_CallRecorder($info->getCallRecorder()),
new Phake_ClassGenerator_InvocationHandler_MagicCallRecorder($info->getCallRecorder()),
new Phake_ClassGenerator_InvocationHandler_StubCaller($info->getStubMapper(), $info->getDefaultAnswer(
)),
))
);
$info->getStubMapper()->mapStubToMatcher(
new Phake_Stubber_AnswerCollection(new Phake_Stubber_Answers_StaticAnswer('Mock for ' . $info->getName())),
new Phake_Matchers_MethodMatcher('__toString', null)
);
return $info;
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* The default client adapter used by Phake.
*/
class Phake_Client_Default implements Phake_Client_IClient
{
public function processVerifierResult(Phake_CallRecorder_VerifierResult $result)
{
if ($result->getVerified()) {
return $result->getMatchedCalls();
} else {
throw new Phake_Exception_VerificationException($result->getFailureDescription());
}
}
public function processObjectFreeze()
{
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Defines the interface for Phake clients.
*/
interface Phake_Client_IClient
{
/**
* Handles the processing of a verifier result. When the verifier is true it should return the matched calls.
* The behavior for if the verifier is false is up to the client.
*
* @param Phake_CallRecorder_VerifierResult $result
*/
public function processVerifierResult(Phake_CallRecorder_VerifierResult $result);
/**
* Used to notify the client that a mock has been frozen.
*/
public function processObjectFreeze();
}

View File

@ -0,0 +1,75 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* The client adapter used for PHPUnit.
*
* This adapter allows PHPUnit to report failed verify() calls as test failures instead of errors. It also counts
* verify() calls as assertions.
*/
class Phake_Client_PHPUnit implements Phake_Client_IClient
{
public function processVerifierResult(Phake_CallRecorder_VerifierResult $result)
{
PHPUnit_Framework_Assert::assertThat($result, $this->getConstraint());
return $result->getMatchedCalls();
}
public function processObjectFreeze()
{
PHPUnit_Framework_Assert::assertThat(true, PHPUnit_Framework_Assert::isTrue());
}
private function getConstraint()
{
if (version_compare('3.6.0', PHPUnit_Runner_Version::id()) == 1) {
return new Phake_PHPUnit_VerifierResultConstraint();
} else {
return new Phake_PHPUnit_VerifierResultConstraintV3d6();
}
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Thrown when a method call doesn't match an expection
*/
class Phake_Exception_MethodMatcherException extends Exception
{
private $argument;
/**
* @param string $message
* @param Exception $previous
*/
public function __construct($message = "", Exception $previous = null)
{
parent::__construct($message, 0, $previous);
$this->argument = 0;
}
/**
* Updates the argument position (used in the argument chain)
*/
public function incrementArgumentPosition()
{
$this->argument++;
}
/**
* Returns the argument's position (0 indexed)
* @return int
*/
public function getArgumentPosition()
{
return $this->argument;
}
}

View File

@ -0,0 +1,13 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: mikel
* Date: 11/25/11
* Time: 10:09 PM
* To change this template use File | Settings | File Templates.
*/
class Phake_Exception_VerificationException extends Exception
{
}

View File

@ -0,0 +1,145 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A facade class providing functionality to interact with the Phake framework.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Facade
{
private $cachedClasses;
/**
* @var Phake_Mock_InfoRegistry
*/
private $infoRegistry;
/**
* @param Phake_Mock_InfoRegistry $infoRegistry
*/
public function __construct(Phake_Mock_InfoRegistry $infoRegistry)
{
$this->cachedClasses = array();
$this->infoRegistry = $infoRegistry;
}
/**
* Creates a new mock class than can be stubbed and verified.
*
* @param string|array $mockedClassList - The name(s) of the class to mock
* @param Phake_ClassGenerator_MockClass $mockGenerator - The generator used to construct mock classes
* @param Phake_CallRecorder_Recorder $callRecorder
* @param Phake_Stubber_IAnswer $defaultAnswer
* @param array $constructorArgs
*
* @throws InvalidArgumentException
* @return mixed
*/
public function mock(
$mockedClassList,
Phake_ClassGenerator_MockClass $mockGenerator,
Phake_CallRecorder_Recorder $callRecorder,
Phake_Stubber_IAnswer $defaultAnswer,
array $constructorArgs = null
) {
$mockedClassList = (array)$mockedClassList;
foreach ($mockedClassList as $mockedClass)
if (!class_exists($mockedClass, true) && !interface_exists($mockedClass, true)) {
throw new InvalidArgumentException("The class / interface [{$mockedClass}] does not exist. Check the spelling and make sure it is loadable.");
}
if (!isset($this->cachedClasses[implode('__', $mockedClassList)])) {
$newClassName = $this->generateUniqueClassName($mockedClassList);
$mockGenerator->generate($newClassName, $mockedClassList, $this->infoRegistry);
$this->cachedClasses[implode('__', $mockedClassList)] = $newClassName;
}
return $mockGenerator->instantiate(
$this->cachedClasses[implode('__', $mockedClassList)],
$callRecorder,
new Phake_Stubber_StubMapper(),
$defaultAnswer,
$constructorArgs
);
}
public function resetStaticInfo()
{
$this->infoRegistry->resetAll();
}
/**
* Generates a unique class name based on a given name.
*
* The $base will be used as the prefix for the new class name.
*
* @param string $base
*
* @return string
*/
private function generateUniqueClassName(array $bases)
{
$base_class_name = array();
foreach ($bases as $base)
{
$ns_parts = explode('\\', $base);
$base = array_pop($ns_parts);
//Cygwin will drop a period from uniqid
$base_class_name[] = str_replace('.', '', uniqid($base . '_PHAKE'));
}
$i = 1;
$base_class_name = implode('__', $base_class_name);
while (class_exists($base_class_name . $i, false)) {
$i++;
}
return $base_class_name . $i;
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* The interface for Phake test double objects.
*
* Just a marker interface.
*/
interface Phake_IMock
{
}

View File

@ -0,0 +1,74 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Implements the base setNextMatcher() getNextMatcher for chaining.
*/
abstract class Phake_Matchers_AbstractChainableArgumentMatcher implements Phake_Matchers_IChainableArgumentMatcher
{
private $nextMatcher;
public function setNextMatcher(Phake_Matchers_IChainableArgumentMatcher $nextMatcher)
{
$nextMatcher->assertPreviousMatcher($this);
$this->nextMatcher = $nextMatcher;
}
/**
* @return Phake_Matchers_IChainableArgumentMatcher
*/
public function getNextMatcher()
{
return $this->nextMatcher;
}
/**
* @param Phake_Matchers_IChainableArgumentMatcher $matcher
* @throws InvalidArgumentException When this matcher cannot be chained to the previous matcher.
* @return null
*/
public function assertPreviousMatcher(Phake_Matchers_IChainableArgumentMatcher $matcher)
{
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A matcher that will return true for any invocation of a particular method
*/
class Phake_Matchers_AnyParameters extends Phake_Matchers_AbstractChainableArgumentMatcher
{
/**
* Do nothing, any parameters always matches
*
* @param array $arguments
*/
public function doArgumentsMatch(array &$arguments)
{
}
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString()
{
return '<any parameters>';
}
public function setNextMatcher(Phake_Matchers_IChainableArgumentMatcher $nextMatcher)
{
throw new InvalidArgumentException('Other matchers cannot be passed with any parameters. It will not work the '
. 'way you think it works');
}
public function assertPreviousMatcher(Phake_Matchers_IChainableArgumentMatcher $matcher)
{
throw new InvalidArgumentException('Other matchers cannot be passed with any parameters. It will not work the '
. 'way you think it works');
}
}

View File

@ -0,0 +1,145 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Used to capture the value passed as a parameter to a verified method for further assertions.
*
* The constructor takes a parameter by reference that is populated when the matching runs.
*/
class Phake_Matchers_ArgumentCaptor extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var mixed
*/
private $boundVariable;
/**
* @var array
*/
private $allCapturedValues;
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $matcher;
/**
* @param mixed $boundVariable - reference parameter
*/
public function __construct(&$boundVariable)
{
$this->boundVariable =& $boundVariable;
$this->allCapturedValues = array();
}
/**
* Binds the passed in variable to the allCapturedValues array
*
* $values will be set to an array
*
* @param array $values
*/
public function bindAllCapturedValues(&$values)
{
$values = $this->allCapturedValues;
$this->allCapturedValues = &$values;
}
/**
* Executes the matcher on a given argument value. Returns TRUE on a match, FALSE otherwise.
*
* Will bind the argument to the variable passed to the constructor.
*
* @param mixed $argument
* @throws Phake_Exception_MethodMatcherException
*/
protected function matches(&$argument)
{
$args = array();
$args[] =& $argument;
if ($this->matcher !== null)
{
try
{
$this->matcher->doArgumentsMatch($args);
}
catch (Phake_Exception_MethodMatcherException $e)
{
throw new Phake_Exception_MethodMatcherException(trim("Failed in Phake::capture()->when()\n" . $e->getMessage()), $e);
}
}
$this->boundVariable = $argument;
$this->allCapturedValues[] = $argument;
}
/**
* Assigns a matcher to the captor.
*
* This allows an argument to only be captured if the argument meets a specific criteria. This
* is useful if one method is called multiple times.
*
* The same matcher factory used by the verifier and stubber is used here.
*
* @param mixed $matcher
*
* @return Phake_Matchers_ArgumentCaptor the current instance
*/
public function when($matcher)
{
$factory = new Phake_Matchers_Factory();
$this->matcher = $factory->createMatcher($matcher);
return $this;
}
public function __toString()
{
return sprintf(
'<captured parameter%s>',
isset($this->matcher) ? " that is {$this->matcher->__toString()}" : ''
);
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Adapts argument matchers into chainable argument matchers.
*/
class Phake_Matchers_ChainedArgumentMatcher extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var Phake_Matchers_IArgumentMatcher
*/
private $adaptedMatcher;
/**
* @param Phake_Matchers_IArgumentMatcher $adaptedMatcher
*/
public function __construct(Phake_Matchers_IArgumentMatcher $adaptedMatcher)
{
$this->adaptedMatcher = $adaptedMatcher;
}
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString()
{
return $this->adaptedMatcher->__toString();
}
public function getAdaptedMatcher()
{
return $this->adaptedMatcher;
}
/**
* Executes the matcher on a given argument value. Returns TRUE on a match, FALSE otherwise.
*
* @param mixed $argument
*
* @return boolean
*/
protected function matches(&$argument)
{
$this->adaptedMatcher->matches($argument);
}
}

View File

@ -0,0 +1,98 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A matcher to validate that an argument equals a particular value.
*
* This matcher utilizes the same functionality as non-strict equality in php, in other words '=='
*/
class Phake_Matchers_EqualsMatcher extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var mixed
*/
private $value;
/**\
* @var \SebastianBergmann\Comparator\Factory
*/
private $comparatorFactory;
/**
* Pass in the value that the upcoming arguments is expected to equal.
*
* @param mixed $value
* @param \SebastianBergmann\Comparator\Factory $comparatorFactory
*/
public function __construct($value, \SebastianBergmann\Comparator\Factory $comparatorFactory)
{
$this->value = $value;
$this->comparatorFactory = $comparatorFactory;
}
/**
* Returns whether or not the passed argument matches the matcher.
*/
protected function matches(&$argument)
{
try
{
$compare = $this->comparatorFactory->getComparatorFor($this->value, $argument);
$compare->assertEquals($this->value, $argument);
}
catch (\SebastianBergmann\Comparator\ComparisonFailure $e)
{
throw new Phake_Exception_MethodMatcherException(trim($e->getMessage() . "\n" . $e->getDiff()), $e);
}
}
/**
* @return string
*/
public function __toString()
{
$converter = new Phake_String_Converter();
return "equal to {$converter->convertToString($this->value)}";
}
}

View File

@ -0,0 +1,117 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Creates (or passes through) instances of Phake_Matchers_IArgumentMatcher using Phake's
* translation rules
*/
class Phake_Matchers_Factory
{
private $comparatorFactory;
public function __construct()
{
$this->comparatorFactory = new \SebastianBergmann\Comparator\Factory();
}
/**
* Creates an argument matcher based on the given value.
*
* If the given values is already an instance of Phake_Matchers_IChainableArgumentMatcher it is passed
* through. If it is an instance of PHPUnit_Framework_Constraint a PHPUnit adapter is returned.
* If it is an instance of Hamcrest_Matcher a Hamcrest adapter is returned. For everything else
* a EqualsMatcher is returned set to the passed in value.
*
* @param mixed $argument
*
* @return Phake_Matchers_IChainableArgumentMatcher
*/
public function createMatcher($argument, Phake_Matchers_IChainableArgumentMatcher $nextMatcher = null)
{
$return = null;
if ($argument instanceof Phake_Matchers_IChainableArgumentMatcher) {
$return = $argument;
} elseif ($argument instanceof PHPUnit_Framework_Constraint) {
$return = new Phake_Matchers_PHPUnitConstraintAdapter($argument);
} elseif ($argument instanceof \PHPUnit\Framework\Constraint\Constraint) {
$return = new Phake_Matchers_PHPUnit6ConstraintAdapter($argument);
} elseif ($argument instanceof Hamcrest\Matcher) {
$return = new Phake_Matchers_HamcrestMatcherAdapter($argument);
} elseif ($argument instanceof Phake_Matchers_IArgumentMatcher) {
$return = new Phake_Matchers_ChainedArgumentMatcher($argument);
} else {
$return = new Phake_Matchers_EqualsMatcher($argument, $this->comparatorFactory);
}
if ($nextMatcher !== null)
{
$return->setNextMatcher($nextMatcher);
}
return $return;
}
/**
* Converts an argument array into a matcher chain
*
* @param array $arguments
*
* @return Phake_Matchers_IChainableArgumentMatcher or null if the arg list was empty
*/
public function createMatcherChain(array $arguments)
{
if (!count($arguments))
{
return null;
}
$lastMatcher = null;
foreach (array_reverse($arguments) as $arg) {
$matcher = $this->createMatcher($arg, $lastMatcher);
$lastMatcher = $matcher;
}
return $lastMatcher;
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An adapter class allowing hamcrest matchers to be used as Phake matchers
*/
class Phake_Matchers_HamcrestMatcherAdapter extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var Hamcrest\Matcher
*/
private $matcher;
/**
* @param Hamcrest\Matcher $matcher
*/
public function __construct(Hamcrest\Matcher $matcher)
{
$this->matcher = $matcher;
}
/**
* Executes the matcher on a given argument value.
*
* Forwards the call to Hamcrest's matches() method.
*
* @param mixed $argument
* @throws Phake_Exception_MethodMatcherException
*/
protected function matches(&$argument)
{
if (!$this->matcher->matches($argument))
{
$description = new \Hamcrest\StringDescription();
$description->appendText("Expected ")
->appendDescriptionOf($this->matcher)
->appendText(' but ');
$this->matcher->describeMismatch($argument, $description);
throw new Phake_Exception_MethodMatcherException($description);
}
}
public function __toString()
{
return $this->matcher->__toString();
}
}

View File

@ -0,0 +1,64 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* The interface for argument matchers
*/
interface Phake_Matchers_IArgumentMatcher
{
/**
* Executes the matcher on a given argument value. Returns TRUE on a match, FALSE otherwise.
*
* @param mixed $argument
*
* @return boolean
*/
public function matches(&$argument);
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString();
}

View File

@ -0,0 +1,88 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An argument collection matcher that can match 0 to many parameters
*/
interface Phake_Matchers_IChainableArgumentMatcher
{
/**
* Assert the matcher on a given list of argument values. Throws an exception if the matcher doesn't match
*
* @param array $arguments
*
* @throw Exception
*/
public function doArgumentsMatch(array &$arguments);
/**
* returns the next matcher in the chain
*
* @return Phake_Matchers_IChainableArgumentMatcher
*/
public function getNextMatcher();
/**
* Sets the next matcher in the chain.
*
* @param Phake_Matchers_IChainableArgumentMatcher $matcher
* @return Phake_Matchers_IChainableArgumentMatcher
* @throws InvalidArgumentException when the given matcher cannot be chained to this matcher
*/
public function setNextMatcher(Phake_Matchers_IChainableArgumentMatcher $matcher);
/**
* Asserts whether or not this matcher can be chained to the the given matcher
*
* @param Phake_Matchers_IChainableArgumentMatcher $matcher
* @throws InvalidArgumentException When this matcher cannot be chained to the previous matcher.
*/
public function assertPreviousMatcher(Phake_Matchers_IChainableArgumentMatcher $matcher);
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString();
}

View File

@ -0,0 +1,72 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Defines the interface for a method matchers.
*
* Method matchers are used to map stubs to method calls, as well as to check for method verifications.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
interface Phake_Matchers_IMethodMatcher
{
/**
* Determines if the given method and arguments match the configured method and argument matchers
* in this object. Returns true on success, false otherwise.
*
* @param string $method
* @param array $args
*
* @return boolean
*/
public function matches($method, array &$args);
/**
* Accessor for the expected method.
*
* @return string
*/
public function getMethod();
}

View File

@ -0,0 +1,72 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A matcher that will return true for any invocation of a particular method
*/
class Phake_Matchers_IgnoreRemainingMatcher extends Phake_Matchers_AbstractChainableArgumentMatcher
{
/**
* Do nothing, ignore remaining always matches
*
* @param array $arguments
*/
public function doArgumentsMatch(array &$arguments)
{
}
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString()
{
return '<any parameters>';
}
public function setNextMatcher(Phake_Matchers_IChainableArgumentMatcher $nextMatcher)
{
throw new InvalidArgumentException('Other matchers cannot be checked after you ignore remaining parameters.');
}
}

View File

@ -0,0 +1,145 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Determines if a method and argument matchers match a given method call.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Matchers_MethodMatcher implements Phake_Matchers_IMethodMatcher
{
/**
* @var string
*/
private $expectedMethod;
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $argumentMatcherChain;
public function __construct($expectedMethod, Phake_Matchers_IChainableArgumentMatcher $argumentMatcherChain = null)
{
$this->expectedMethod = $expectedMethod;
$this->argumentMatcherChain = $argumentMatcherChain;
}
/**
* Determines if the given method and arguments match the configured method and argument matchers
* in this object. Returns true on success, false otherwise.
*
* @param string $method
* @param array $args
*
* @return boolean
*/
public function matches($method, array &$args)
{
try
{
$this->assertMatches($method, $args);
return true;
}
catch (Phake_Exception_MethodMatcherException $e)
{
return false;
}
}
/**
* Asserts whether or not the given method and arguments match the configured method and argument matchers in this \
* object.
*
* @param string $method
* @param array $args
* @return bool
* @throws Phake_Exception_MethodMatcherException
*/
public function assertMatches($method, array &$args)
{
if ($this->expectedMethod != $method)
{
throw new Phake_Exception_MethodMatcherException("Expected method {$this->expectedMethod} but received {$method}");
}
$this->doArgumentsMatch($args);
}
/**
* Determines whether or not given arguments match the argument matchers configured in the object.
*
* Throws an exception with a description if the arguments do not match.
*
* @param array $args
* @return bool
* @throws Phake_Exception_MethodMatcherException
*/
private function doArgumentsMatch(array &$args)
{
if ($this->argumentMatcherChain !== null)
{
try
{
$this->argumentMatcherChain->doArgumentsMatch($args);
}
catch (Phake_Exception_MethodMatcherException $e)
{
$position = $e->getArgumentPosition() + 1;
throw new Phake_Exception_MethodMatcherException(trim("Argument #{$position} failed test\n" . $e->getMessage()), $e);
}
}
elseif (count($args) != 0)
{
throw new Phake_Exception_MethodMatcherException("No matchers were given to Phake::when(), but arguments were received by this method.");
}
}
/**
* @return string
*/
public function getMethod()
{
return $this->expectedMethod;
}
}

View File

@ -0,0 +1,97 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An adapter class allowing PHPUnit constraints to be treated as though they were Phake argument
* matchers.
*/
class Phake_Matchers_PHPUnit6ConstraintAdapter extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var \PHPUnit\Framework\Constraint\Constraint
*/
private $constraint;
/**
* @param \PHPUnit\Framework\Constraint\Constraint $constraint
*/
public function __construct(\PHPUnit\Framework\Constraint\Constraint $constraint)
{
$this->constraint = $constraint;
}
/**
* Executes the matcher on a given argument value.
*
* Forwards the call to PHPUnit's evaluate() method.
*
* @param mixed $argument
* @throws Phake_Exception_MethodMatcherException
*/
protected function matches(&$argument)
{
try
{
$this->constraint->evaluate($argument, '');
}
catch (\PHPUnit\Framework\ExpectationFailedException $e)
{
$failure = $e->getComparisonFailure();
if ($failure instanceof \PHPUnit\Framework\ComparisonFailure)
{
$failure = $failure->getDiff();
}
else
{
$failure = '';
}
throw new Phake_Exception_MethodMatcherException($e->getMessage() . "\n" . $failure, $e);
}
}
public function __toString()
{
return $this->constraint->toString();
}
}

View File

@ -0,0 +1,99 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An adapter class allowing PHPUnit constraints to be treated as though they were Phake argument
* matchers.
*/
class Phake_Matchers_PHPUnitConstraintAdapter extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var PHPUnit_Framework_Constraint
*/
private $constraint;
/**
* @param PHPUnit_Framework_Constraint $constraint
*/
public function __construct(PHPUnit_Framework_Constraint $constraint)
{
$this->constraint = $constraint;
}
/**
* Executes the matcher on a given argument value.
*
* Forwards the call to PHPUnit's evaluate() method.
*
* @param mixed $argument
* @throws Phake_Exception_MethodMatcherException
*/
protected function matches(&$argument)
{
try
{
$this->constraint->evaluate($argument, '');
}
catch (PHPUnit_Framework_ExpectationFailedException $e)
{
$failure = $e->getComparisonFailure();
if ($failure instanceof PHPUnit_Framework_ComparisonFailure)
{
$failure = $failure->getDiff();
}
else
{
$failure = '';
}
throw new Phake_Exception_MethodMatcherException($e->getMessage() . "\n" . $failure, $e);
}
}
public function __toString()
{
return $this->constraint->toString();
}
}

View File

@ -0,0 +1,120 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
class Phake_Matchers_ReferenceSetter extends Phake_Matchers_SingleArgumentMatcher
{
/**
* @var mixed
*/
private $value;
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $matcher;
/**
* @param mixed $value The value to set the reference parameter to.
*/
public function __construct($value)
{
$this->value = $value;
}
/**
* Executes the matcher on a given argument value.
*
* Sets the $argument to the value passed in the constructor
*
* @param mixed $argument
* @throws Phake_Exception_MethodMatcherException
*/
protected function matches(&$argument)
{
$args = array();
$args[] =& $argument;
if ($this->matcher !== null)
{
try
{
$this->matcher->doArgumentsMatch($args);
}
catch (Phake_Exception_MethodMatcherException $e)
{
throw new Phake_Exception_MethodMatcherException(trim("Failed in Phake::setReference()->when()\n" . $e->getMessage()), $e);
}
$this->matcher->doArgumentsMatch($args);
}
$argument = $this->value;
}
/**
* Returns a human readable description of the argument matcher
* @return string
*/
public function __toString()
{
return '<reference parameter>';
}
/**
* Assigns a matcher to the setter.
*
* This allows an argument to only be set if the original argument meets a specific criteria.
*
* The same matcher factory used by the verifier and stubber is used here.
*
* @param mixed $matcher
*
* @return Phake_Matchers_ReferenceSetter the current instance
*/
public function when($matcher)
{
$factory = new Phake_Matchers_Factory();
$this->matcher = $factory->createMatcher($matcher);
return $this;
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Implements matches so that you can easily match a single argument
*/
abstract class Phake_Matchers_SingleArgumentMatcher extends Phake_Matchers_AbstractChainableArgumentMatcher {
/**
* Executes the matcher on a given list of argument values. Returns TRUE on a match, FALSE otherwise.
*
* @param array $arguments
* @throws Phake_Exception_MethodMatcherException
*/
public function doArgumentsMatch(array &$arguments)
{
$argumentCopy = $arguments;
$nextArgument =& $arguments[0];
array_shift($argumentCopy);
$this->matches($nextArgument);
$nextMatcher = $this->getNextMatcher();
if (!isset($nextMatcher))
{
if (count($argumentCopy) != 0)
{
throw new Phake_Exception_MethodMatcherException("There were more arguments than matchers");
}
}
else
{
try
{
$this->getNextMatcher()->doArgumentsMatch($argumentCopy);
}
catch (Phake_Exception_MethodMatcherException $e)
{
$e->incrementArgumentPosition();
throw $e;
}
}
}
/**
* Asserts the matcher on a given argument value. Throws an exception on false
*
* @param mixed $argument
*/
abstract protected function matches(&$argument);
}

View File

@ -0,0 +1,65 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Freezes a mock so that no other calls can be made
*
* @see Phake_ClassGeneration_InvocationHandler_FrozenObjectCheck
*/
class Phake_Mock_Freezer
{
/**
* Freezes the given $mock and notifies the given $client
*
* @param Phake_Mock_Info $mockInfo
* @param Phake_Client_IClient $client
*/
public function freeze(Phake_Mock_Info $mockInfo, Phake_Client_IClient $client)
{
$client->processObjectFreeze();
$mockInfo->freezeObject();
}
}

View File

@ -0,0 +1,130 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Stores data about the mock object.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Mock_Info {
private $uniqId;
private $recorder;
private $mapper;
private $answer;
private $frozen;
private $name;
/**
* @var Phake_ClassGenerator_InvocationHandler_IInvocationHandler
*/
private $handlerChain;
public function __construct($name, Phake_CallRecorder_Recorder $recorder, Phake_Stubber_StubMapper $mapper, Phake_Stubber_IAnswer $defaultAnswer)
{
$this->uniqId = uniqid('', true);
$this->recorder = $recorder;
$this->mapper = $mapper;
$this->answer = $defaultAnswer;
$this->frozen = false;
$this->name = $name;
}
public function getCallRecorder()
{
return $this->recorder;
}
public function getStubMapper()
{
return $this->mapper;
}
public function getDefaultAnswer()
{
return $this->answer;
}
public function isObjectFrozen()
{
return $this->frozen;
}
public function freezeObject()
{
$this->frozen = true;
}
public function thawObject()
{
$this->frozen = false;
}
public function getHandlerChain()
{
return $this->handlerChain;
}
public function setHandlerChain(Phake_ClassGenerator_InvocationHandler_IInvocationHandler $handlerChain)
{
$this->handlerChain = $handlerChain;
}
public function getName()
{
return $this->name;
}
public function resetInfo()
{
$this->thawObject();
$this->mapper->removeAllAnswers();
$this->recorder->removeAllCalls();
}
}

View File

@ -0,0 +1,64 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Stores all Phake_Mock_Info instances for static classes.
*/
class Phake_Mock_InfoRegistry {
private $registry = array();
public function addInfo(Phake_Mock_Info $info)
{
$this->registry[] = $info;
}
public function resetAll()
{
/* @var $info Phake_Mock_Info */
foreach ($this->registry as $info)
{
$info->resetInfo();
}
}
}

View File

@ -0,0 +1,73 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A PHPUnit constraint that wraps a phake verifier to allow assertions on expected calls.
*/
class Phake_PHPUnit_VerifierResultConstraint extends PHPUnit_Framework_Constraint
{
public function evaluate($other, $description = '', $returnResult = FALSE)
{
if (!$other instanceof Phake_CallRecorder_VerifierResult) {
throw new InvalidArgumentException("You must pass an instance of Phake_CallRecorder_VerifierResult");
}
return $other->getVerified();
}
public function toString()
{
return 'is called';
}
protected function customFailureDescription($other, $description, $not)
{
if (!$other instanceof Phake_CallRecorder_VerifierResult) {
throw new InvalidArgumentException("You must pass an instance of Phake_CallRecorder_VerifierResult");
}
return $other->getFailureDescription();
}
}

View File

@ -0,0 +1,73 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A PHPUnit constraint that wraps a phake verifier to allow assertions on expected calls.
*/
class Phake_PHPUnit_VerifierResultConstraintV3d6 extends PHPUnit_Framework_Constraint
{
protected function matches($other)
{
if (!$other instanceof Phake_CallRecorder_VerifierResult) {
throw new InvalidArgumentException("You must pass an instance of Phake_CallRecorder_VerifierResult");
}
return $other->getVerified();
}
public function toString()
{
return 'is called';
}
protected function failureDescription($other)
{
if (!$other instanceof Phake_CallRecorder_VerifierResult) {
throw new InvalidArgumentException("You must pass an instance of Phake_CallRecorder_VerifierResult");
}
return $other->getFailureDescription();
}
}

View File

@ -0,0 +1,148 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A proxy class to provide a fluent interface into the answer binder.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_AnswerBinderProxy
{
/**
* @var Phake_Stubber_IAnswerBinder
*/
private $binder;
public function __construct(Phake_Stubber_IAnswerBinder $binder)
{
$this->binder = $binder;
}
/**
* Binds a static answer to the method and object in the proxied binder.
*
* @param mixed $value
*
* @return Phake_Stubber_IAnswerContainer
*/
public function thenReturn($value)
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_StaticAnswer($value));
}
/**
* Binds a Lambda answer to the method
*
* @param callback $value
*
* @deprecated Use thenReturnCallback instead.
* @throws InvalidArgumentException
* @return Phake_Stubber_IAnswerContainer
*/
public function thenGetReturnByLambda($value)
{
trigger_error('Use thenReturnCallback instead.', E_USER_DEPRECATED);
return $this->thenReturnCallback($value);
}
/**
* Binds a callback answer to the method.
*
* @param callback $value
*
* @throws InvalidArgumentException
* @return Phake_Stubber_IAnswerContainer
*/
public function thenReturnCallback($value)
{
if (!is_callable($value)) {
throw new InvalidArgumentException("Given lambda is not callable");
}
return $this->binder->bindAnswer(new Phake_Stubber_Answers_LambdaAnswer($value));
}
/**
* Binds a delegated call that will call a given method's parent.
* @return Phake_Stubber_IAnswerContainer
*/
public function thenCallParent()
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_ParentDelegate());
}
/**
* Binds an exception answer to the method and object in the proxied binder.
*
* @param Exception $value
*
* @return Phake_Stubber_IAnswerContainer
*/
public function thenThrow(Exception $value)
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_ExceptionAnswer($value));
}
/**
* Binds a delegated call that will call a given method's parent while capturing that value to the passed in variable.
*
* @param mixed $captor
*
* @return Phake_Stubber_IAnswerContainer
*/
public function captureReturnTo(&$captor)
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_ParentDelegate($captor));
}
public function thenDoNothing()
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_NoAnswer());
}
public function thenReturnSelf()
{
return $this->binder->bindAnswer(new Phake_Stubber_Answers_SelfAnswer());
}
}

View File

@ -0,0 +1,141 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A proxy class to provide Stub Chaining through use of an AnswerCollection
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_AnswerCollectionProxy implements Phake_Stubber_IAnswerContainer
{
/**
* @var Phake_Stubber_AnswerCollection
*/
private $collection;
/**
* @param Phake_Stubber_AnswerCollection $collection
*/
public function __construct(Phake_Stubber_AnswerCollection $collection)
{
$this->collection = $collection;
}
/**
* Binds a static answer to the method and object in the proxied binder.
*
* @param mixed $value
*
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function thenReturn($value)
{
$this->collection->addAnswer(new Phake_Stubber_Answers_StaticAnswer($value));
return $this;
}
/**
* Binds a Lambda answer to the method
*
* @param callback $value
*
* @throws InvalidArgumentException
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function thenGetReturnByLambda($value)
{
if (!is_callable($value)) {
throw new InvalidArgumentException("Given lambda is not callable");
}
$this->collection->addAnswer(new Phake_Stubber_Answers_LambdaAnswer($value));
return $this;
}
/**
* Binds a delegated call that will call a given method's parent.
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function thenCallParent()
{
$this->collection->addAnswer(new Phake_Stubber_Answers_ParentDelegate());
return $this;
}
/**
* Binds an exception answer to the method and object in the proxied binder.
*
* @param Exception $value
*
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function thenThrow(Exception $value)
{
$this->collection->addAnswer(new Phake_Stubber_Answers_ExceptionAnswer($value));
return $this;
}
/**
* Binds a delegated call that will call a given method's parent while capturing that value to the passed in variable.
*
* @param mixed $captor
*
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function captureReturnTo(&$captor)
{
$this->collection->addAnswer(new Phake_Stubber_Answers_ParentDelegate($captor));
return $this;
}
/**
* Returns an answer from the container
* @return Phake_Stubber_IAnswer
*/
public function getAnswer()
{
return $this->collection->getAnswer();
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A proxy to handle stubbing various calls to the magic __call method
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_CallStubberProxy
{
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $argumentMatcher;
/**
* @var bool
*/
private $static;
/**
* @param Phake_Matchers_IChainableArgumentMatcher $argumentMatcher
* @param bool $static
*/
public function __construct(Phake_Matchers_IChainableArgumentMatcher $argumentMatcher = null, $static)
{
$this->argumentMatcher = $argumentMatcher;
$this->static = $static;
}
/**
* Creates an answer binder proxy associated with the matchers from the constructor and the object passed here
*
* @param Phake_IMock $obj
*
* @return Phake_Proxies_AnswerBinderProxy
*/
public function isCalledOn(Phake_IMock $obj)
{
$context = $this->static ? get_class($obj) : $obj;
$call = $this->static ? '__callStatic' : '__call';
$matcher = new Phake_Matchers_MethodMatcher($call, $this->argumentMatcher);
$binder = new Phake_Stubber_AnswerBinder($matcher, Phake::getInfo($context)->getStubMapper());
return new Phake_Proxies_AnswerBinderProxy($binder);
}
}

View File

@ -0,0 +1,105 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A proxy to handle verifying various calls to the magic __call method
*
* The parameters that you would like to verify are passed into the constructor.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_CallVerifierProxy
{
/**
* @var Phake_Matchers_IChainableArgumentMatcher
*/
private $argumentMatcher;
/**
* @var Phake_Client_IClient
*/
private $client;
/**
* @var bool
*/
private $static;
/**
* @param Phake_Matchers_IChainableArgumentMatcher $argumentMatcher
* @param Phake_Client_IClient $client
* @param bool $static
*/
public function __construct(Phake_Matchers_IChainableArgumentMatcher $argumentMatcher = null, Phake_Client_IClient $client, $static)
{
$this->argumentMatcher = $argumentMatcher;
$this->client = $client;
$this->static = $static;
}
/**
* Verifies that the call to __call was made on the given object with the parameters passed into the constructor
*
* @param Phake_IMock $obj
* @param Phake_CallRecorder_IVerifierMode $verifierMode
*
* @return array
*/
public function isCalledOn(Phake_IMock $obj, Phake_CallRecorder_IVerifierMode $verifierMode = null)
{
if ($verifierMode === null) {
$verifierMode = new Phake_CallRecorder_VerifierMode_Times(1);
}
$context = $this->static ? get_class($obj) : $obj;
$call = $this->static ? '__callStatic' : '__call';
$verifier = new Phake_CallRecorder_Verifier(Phake::getInfo($context)->getCallRecorder(), $obj);
$expectation = new Phake_CallRecorder_CallExpectation($context, $call, $this->argumentMatcher, $verifierMode);
$result = $verifier->verifyCall($expectation);
return $this->client->processVerifierResult($result);
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2015, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Acts as a proxy to any object that allows calling any private or protected method on the wrapper and forward those
* calls to the wrapped object.
*
* I debated alot about putting anything like this in Phake and at some point I may just pull it out into its own
* library. It should be used with great caution and should really only need to be used to help ease steps in
* refactoring of otherwise hard to reach private and protected methods
*
* @author Mike Lively <m@digitalsandwich.com>
* @internal This class will quite likely change soon, don't use it outside of phake code
*/
class Phake_Proxies_StaticVisibilityProxy
{
private $proxied;
public function __construct($proxied)
{
if (!is_object($proxied))
{
throw new InvalidArgumentException("Phake_Proxies_VisibilityProxy was passed a non-object");
}
$this->proxied = get_class($proxied);
}
/**
* @param $method
* @param $arguments
* @return mixed
*/
public function __call($method, $arguments)
{
if (method_exists($this->proxied, $method))
{
$reflMethod = new ReflectionMethod($this->proxied, $method);
$reflMethod->setAccessible(true);
return $reflMethod->invokeArgs(null, $arguments);
}
elseif (method_exists($this->proxied, '__callStatic'))
{
$reflMethod = new ReflectionMethod($this->proxied, '__callStatic');
return $reflMethod->invokeArgs(null, func_get_args());
}
else
{
throw new InvalidArgumentException("Method {$method} does not exist on {$this->proxied}");
}
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A proxy to handle stubbing a method on a mock object.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_StubberProxy
{
/**
* @var Phake_IMock
*/
private $obj;
/**
* @var Phake_Matchers_Factory
*/
private $matcherFactory;
/**
* @param Phake_IMock|string $obj
* @param Phake_Matchers_Factory $matcherFactory
*/
public function __construct($obj, Phake_Matchers_Factory $matcherFactory)
{
Phake::assertValidMock($obj);
$this->obj = $obj;
$this->matcherFactory = $matcherFactory;
}
/**
* A magic call to instantiate an Answer Binder Proxy.
*
* @param string $method
* @param array $arguments
*
* @return Phake_Proxies_AnswerBinderProxy
*/
public function __call($method, array $arguments)
{
$matcher = new Phake_Matchers_MethodMatcher($method, $this->matcherFactory->createMatcherChain($arguments));
$binder = new Phake_Stubber_AnswerBinder($matcher, Phake::getInfo($this->obj)->getStubMapper());
return new Phake_Proxies_AnswerBinderProxy($binder);
}
/**
* A magic call to instantiate an Answer Binder Proxy that matches any parameters.
*
* @param string $method
*
* @throws InvalidArgumentException if $method is not a valid parameter/method name
*
* @return Phake_Proxies_AnswerBinderProxy
*/
public function __get($method)
{
if (is_string($method) && ctype_digit($method[0])) {
throw new InvalidArgumentException('String parameter to __get() cannot start with an integer');
}
if (!is_string($method) && !is_object($method)) { // assume an object is a matcher
$message = sprintf('Parameter to __get() must be a string, %s given', gettype($method));
throw new InvalidArgumentException($message);
}
if (method_exists($this->obj, '__get') && !(is_string($method) && method_exists($this->obj, $method))) {
return $this->__call('__get', array($method));
}
return $this->__call($method, array(new Phake_Matchers_AnyParameters()));
}
}

View File

@ -0,0 +1,140 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Acts as a proxy to Phake_CallRecorder_Verifier that allows verifying methods using the magic
* __call() method in PHP.
*
* Also throws an exception when a verification call fails.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Proxies_VerifierProxy
{
/**
* @var Phake_CallRecorder_Verifier
*/
private $verifier;
/**
* @var Phake_Matchers_Factory
*/
private $matcherFactory;
/**
* @var Phake_CallRecorder_IVerifierMode
*/
private $mode;
/**
*
* @var Phake_Client_IClient
*/
private $client;
/**
* @param Phake_CallRecorder_Verifier $verifier
* @param Phake_Matchers_Factory $matcherFactory
* @param Phake_CallRecorder_IVerifierMode $mode
* @param Phake_Client_IClient $client
*/
public function __construct(
Phake_CallRecorder_Verifier $verifier,
Phake_Matchers_Factory $matcherFactory,
Phake_CallRecorder_IVerifierMode $mode,
Phake_Client_IClient $client
) {
$this->verifier = $verifier;
$this->matcherFactory = $matcherFactory;
$this->mode = $mode;
$this->client = $client;
}
/**
* A call magic method to provide a more fluent interface to the verifier.
*
* @param string $method
* @param array $arguments
*
* @return Phake_CallRecorder_VerifierResult
*/
public function __call($method, array $arguments)
{
$expectation = new Phake_CallRecorder_CallExpectation($this->verifier->getObject(
), $method, $this->matcherFactory->createMatcherChain($arguments), $this->mode);
$result = $this->verifier->verifyCall($expectation);
return $this->client->processVerifierResult($result);
}
/**
* A magic call to verify a call with any parameters.
*
* @param string $method
*
* @throws InvalidArgumentException if $method is not a valid parameter/method name
*
* @return Phake_CallRecorder_VerifierResult
*/
public function __get($method)
{
$obj = $this->verifier->getObject();
if (is_string($method) && ctype_digit($method[0])) {
throw new InvalidArgumentException('String parameter to __get() cannot start with an integer');
}
if (!is_string($method) && !is_object($method)) {
$message = sprintf('Parameter to __get() must be a string, %s given', gettype($method));
throw new InvalidArgumentException($message);
}
if (method_exists($obj, '__get') && !(is_string($method) && method_exists($obj, $method))) {
return $this->__call('__get', array($method));
}
return $this->__call($method, array(new Phake_Matchers_AnyParameters));
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2015, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Acts as a proxy to any object that allows calling any private or protected method on the wrapper and forward those
* calls to the wrapped object.
*
* I debated alot about putting anything like this in Phake and at some point I may just pull it out into its own
* library. It should be used with great caution and should really only need to be used to help ease steps in
* refactoring of otherwise hard to reach private and protected methods
*
* @author Mike Lively <m@digitalsandwich.com>
* @internal This class will quite likely change soon, don't use it outside of phake code
*/
class Phake_Proxies_VisibilityProxy
{
private $proxied;
public function __construct($proxied)
{
if (!is_object($proxied))
{
throw new InvalidArgumentException("Phake_Proxies_VisibilityProxy was passed a non-object");
}
$this->proxied = $proxied;
}
/**
* @param $method
* @param $arguments
* @return mixed
*/
public function __call($method, $arguments)
{
if (method_exists($this->proxied, $method))
{
$reflMethod = new ReflectionMethod(get_class($this->proxied), $method);
$reflMethod->setAccessible(true);
return $reflMethod->invokeArgs($this->proxied, $arguments);
}
elseif (method_exists($this->proxied, '__call'))
{
$reflMethod = new ReflectionMethod(get_class($this->proxied), '__call');
return $reflMethod->invokeArgs($this->proxied, func_get_args());
}
else
{
throw new InvalidArgumentException("Method {$method} does not exist on " . get_class($this->proxied) . '.');
}
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A converter that accepts any variable and converts it to a printable string
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_String_Converter
{
public function convertToString($value)
{
if (is_object($value)) {
$strValue = '<object:' . get_class($value) . '>';
} elseif (is_array($value)) {
$strValue = '<array>';
} elseif (is_null($value)) {
$strValue = '<null>';
} elseif (is_resource($value)) {
$strValue = '<resource>';
} elseif (is_bool($value)) {
$strValue = '<boolean:' . ($value ? 'true' : 'false') . '>';
} else {
$strValue = '<' . gettype($value) . ':' . $value . '>';
}
return $strValue;
}
}

View File

@ -0,0 +1,90 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows binding an answer to stubbable object's method.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Stubber_AnswerBinder implements Phake_Stubber_IAnswerBinder
{
/**
* @var Phake_Matchers_MethodMatcher
*/
private $matcher;
/**
* @var Phake_Stubber_StubMapper
*/
private $stubMapper;
/**
* Creates a new Answer Binder
*
* @param Phake_Matchers_MethodMatcher $matcher
* @param Phake_Stubber_StubMapper $stubMapper
*/
public function __construct(Phake_Matchers_MethodMatcher $matcher, Phake_Stubber_StubMapper $stubMapper)
{
$this->matcher = $matcher;
$this->stubMapper = $stubMapper;
}
/**
* Binds an answer to the the classes
*
* @param Phake_Stubber_IAnswer $answer
*
* @return Phake_Proxies_AnswerCollectionProxy
*/
public function bindAnswer(Phake_Stubber_IAnswer $answer)
{
$collection = new Phake_Stubber_AnswerCollection($answer);
$this->stubMapper->mapStubToMatcher($collection, $this->matcher);
return new Phake_Proxies_AnswerCollectionProxy($collection);
}
}

View File

@ -0,0 +1,97 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows iteration over a series of answers. Simply calling getAnswer() will result in the appropriate
* answer being returned. You do not need to manage the iteration manually.
*
* If there are no answers left to return, the last answer is returned again.
*/
class Phake_Stubber_AnswerCollection implements Phake_Stubber_IAnswerContainer
{
/**
* @var array
*/
private $answers;
/**
* Adds the passed answer to a new answer collection.
*
* @param Phake_Stubber_IAnswer $answer
*/
public function __construct(Phake_Stubber_IAnswer $answer)
{
$this->answers = array($answer);
}
/**
* Adds a new answer to the end of the collection.
*
* @param Phake_Stubber_IAnswer $answer
*/
public function addAnswer(Phake_Stubber_IAnswer $answer)
{
$this->answers[] = $answer;
}
/**
* Returns the next answer in the collection.
*
* @return Phake_Stubber_IAnswer
*/
public function getAnswer()
{
$answer = current($this->answers);
if ($answer === false) {
$answer = end($this->answers);
}
next($this->answers);
return $answer;
}
}

View File

@ -0,0 +1,76 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows providing an exception to throw to a stubbed method call.
*
* @author Brian Feaver <brian.feaver@gmail.com>
*/
class Phake_Stubber_Answers_ExceptionAnswer implements Phake_Stubber_IAnswer
{
/**
* @var mixed
*/
private $answer;
/**
* @param mixed $answer
*/
public function __construct(Exception $answer)
{
$this->answer = $answer;
}
public function getAnswerCallback($context, $method)
{
$answer = $this->answer;
return function () use ($answer) {
throw $answer;
};
}
public function processAnswer($answer)
{
}
}

View File

@ -0,0 +1,50 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Thrown when an invalid answer is created or used
*/
class Phake_Stubber_Answers_InvalidAnswerException extends LogicException
{
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Allows providing a static answer to a stubbed method call.
*
* @author Mathieu Kooiman <mathieuk@gmail.com>
*/
class Phake_Stubber_Answers_LambdaAnswer implements Phake_Stubber_IAnswer
{
/**
* @var mixed
*/
private $answerLambda;
/**
* @param mixed $answerLambda
*/
public function __construct($answerLambda)
{
$this->answerLambda = $answerLambda;
}
/**
* Nothing to process
*
* @param mixed $answer
*
* @return null
*/
public function processAnswer($answer)
{
}
public function getAnswerCallback($context, $method)
{
return $this->answerLambda;
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows providing a static answer to a stubbed method call.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Stubber_Answers_NoAnswer extends Phake_Stubber_Answers_StaticAnswer
{
public function __construct()
{
parent::__construct(null);
}
}

View File

@ -0,0 +1,106 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* An answer delegate that allows mocked methods to call their parent methods.
*
* If a particular method does not have a parent (ie abstract methods) then a static null answer (effectively) is used
* instead.
*
* This class is both the delegator and the delegate.
*/
class Phake_Stubber_Answers_ParentDelegate implements Phake_Stubber_IAnswer
{
private $capturedReturn;
public function __construct(&$captor = null)
{
$this->capturedReturn =& $captor;
}
public function processAnswer($answer)
{
$this->capturedReturn = $answer;
}
public function getAnswerCallback($context, $method)
{
$fallback = array($this, "getFallback");
try
{
$reflClass = new ReflectionClass($context);
$reflParent = $reflClass->getParentClass();
if (!is_object($reflParent))
{
return $fallback;
}
$reflMethod = $reflParent->getMethod($method);
if (!$reflMethod->isAbstract())
{
if (defined('HHVM_VERSION'))
{
return array('parent', $method);
}
else
{
return new Phake_Stubber_Answers_ParentDelegateCallback($context, $reflMethod);
}
}
}
catch (ReflectionException $e)
{
}
return $fallback;
}
public function getFallback()
{
return null;
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* A callable class that allows for calling parent methods without losing references.
*/
class Phake_Stubber_Answers_ParentDelegateCallback
{
private $context;
/**
* @var ReflectionMethod
*/
private $parentMethod;
public function __construct($context, ReflectionMethod $parentMethod)
{
$this->context = $context;
$this->parentMethod = $parentMethod;
}
public function __invoke(array $arguments)
{
$this->parentMethod->setAccessible(true);
if ($this->parentMethod->isStatic())
{
$context = null;
}
else
{
$context = $this->context;
}
return $this->parentMethod->invokeArgs($context, $arguments);
}
}

View File

@ -0,0 +1,74 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
class Phake_Stubber_Answers_SelfAnswer implements Phake_Stubber_IAnswer
{
/**
* Returns the answer that should be used when a method stubbed to this answer is called.
* @param mixed $context class name or object instance
* @param string $method
* @return callable
*/
public function getAnswerCallback($context, $method)
{
if (!is_object($context))
{
throw new Phake_Stubber_Answers_InvalidAnswerException("Invalid context for " . __CLASS__ . ". You can only use this answer on non-static methods");
}
return function () use ($context)
{
return $context;
};
}
/**
* Allows for post processing an answer if necessary
* @param mixed $answer
* @return mixed
*/
public function processAnswer($answer)
{
}
}

View File

@ -0,0 +1,102 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Returns the proper default value for a method based on the return type.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Stubber_Answers_SmartDefaultAnswer implements Phake_Stubber_IAnswer
{
public function processAnswer($answer)
{
}
public function getAnswerCallback($context, $method)
{
$class = new ReflectionClass($context);
$method = $class->getMethod($method);
$defaultAnswer = null;
if (method_exists($method, 'hasReturnType') && $method->hasReturnType())
{
switch ((string)$method->getReturnType())
{
case 'int':
$defaultAnswer = 0;
break;
case 'float':
$defaultAnswer = 0.0;
break;
case 'string':
$defaultAnswer = "";
break;
case 'bool':
$defaultAnswer = false;
break;
case 'array':
$defaultAnswer = array();
break;
case 'callable':
$defaultAnswer = function () {};
break;
default:
if (class_exists((string)$method->getReturnType()))
{
$defaultAnswer = Phake::mock((string)$method->getReturnType());
}
break;
}
}
return function () use ($defaultAnswer)
{
return $defaultAnswer;
};
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Allows providing a static answer to a stubbed method call.
*
* @author Mike Lively <m@digitalsandwich.com>
*/
class Phake_Stubber_Answers_StaticAnswer implements Phake_Stubber_IAnswer
{
/**
* @var mixed
*/
private $answer;
/**
* @param mixed $answer
*/
public function __construct($answer)
{
$this->answer = $answer;
}
public function processAnswer($answer)
{
}
public function getAnswerCallback($context, $method)
{
$answer = $this->answer;
return function () use ($answer) {
return $answer;
};
}
}

View File

@ -0,0 +1,65 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Defines an interface for answers
*/
interface Phake_Stubber_IAnswer
{
/**
* Returns the answer that should be used when a method stubbed to this answer is called.
* @param mixed $context class name or object instance
* @param string $method
* @return callable
*/
public function getAnswerCallback($context, $method);
/**
* Allows for post processing an answer if necessary
* @param mixed $answer
* @return mixed
*/
public function processAnswer($answer);
}

View File

@ -0,0 +1,60 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010-2012, Mike Lively <m@digitalsandwich.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Provides the interface for an answer binder
*/
interface Phake_Stubber_IAnswerBinder
{
/**
* Binds the given answer to an object.
*
* Returns an answer container that will contain the given answer.
*
* @param Phake_Stubber_IAnswer $answer
*
* @return Phake_Stubber_IAnswerContainer
*/
public function bindAnswer(Phake_Stubber_IAnswer $answer);
}

View File

@ -0,0 +1,55 @@
<?php
/*
* Phake - Mocking Framework
*
* Copyright (c) 2010, Mike Lively <mike.lively@sellingsource.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Mike Lively nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package Phake
* @author Mike Lively <m@digitalsandwich.com>
* @copyright 2010 Mike Lively <m@digitalsandwich.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.digitalsandwich.com/
*/
/**
* Answer containers are classes used to store answers.
*/
interface Phake_Stubber_IAnswerContainer
{
/**
* Returns an answer from the container
* @return Phake_Stubber_IAnswer
*/
public function getAnswer();
}

Some files were not shown because too many files have changed in this diff Show More