Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kenjis/monkey-patch
Standalone package of ci-phpunit-test's Monkey Patching.
https://github.com/kenjis/monkey-patch
hacktoberfest monkey-patch monkey-patching phpunit testing
Last synced: 4 months ago
JSON representation
Standalone package of ci-phpunit-test's Monkey Patching.
- Host: GitHub
- URL: https://github.com/kenjis/monkey-patch
- Owner: kenjis
- License: mit
- Created: 2021-03-04T09:55:25.000Z (almost 4 years ago)
- Default Branch: 1.x
- Last Pushed: 2021-07-14T08:05:49.000Z (over 3 years ago)
- Last Synced: 2024-04-25T06:21:25.955Z (9 months ago)
- Topics: hacktoberfest, monkey-patch, monkey-patching, phpunit, testing
- Language: PHP
- Homepage:
- Size: 185 KB
- Stars: 4
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Monkey Patch
This package is a standalone package of [ci-phpunit-test](https://github.com/kenjis/ci-phpunit-test) 's Monkey Patching.
This provides four monkey patchers.
- `ExitPatcher`: Converts `exit()` to Exception
- `FunctionPatcher`: Patches Functions
- `MethodPatcher`: Patches Methods in User-defined Classes
- `ConstantPatcher`: Changes Constant Values## Table of Contents
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Configure](#configure)
- [Convert `exit()` to Exception](#convert-exit-to-exception)
- [Patch Functions](#patch-functions)
- [Change Return Value](#change-return-value)
- [Patch Other Functions](#patch-other-functions)
- [Patch Methods in User-defined Classes](#patch-methods-in-user-defined-classes)
- [Patch Constants](#patch-constants)
- [Class Reference](#class-reference)
- [License](#license)## Requirements
- PHP 7.3 or later
## Installation
```sh-session
$ composer require --dev kenjis/monkey-patch
```## Usage
**Note:** The line number when an error occurs is probably different from the actual source code. Please check the cache file of the source that Monkey Patching creates.
**Note:** Using this package has a negative impact on speed of tests.
### Configure
- To enable monkey patching, add [the content of the bootstrap](https://github.com/kenjis/monkey-patch/blob/1.x/src/bootstrap.php) in your PHPUnit bootstrap file.
- Set [MonkeyPatchManager::init()](https://github.com/kenjis/monkey-patch/blob/f5b1839a01c0c3cd56f4873e8c307b0583a5526b/src/bootstrap.php#L31-L61) arguments.
- To verify invocations, use the [MonkeyPatchTrait](https://github.com/kenjis/monkey-patch/blob/1.x/src/Traits/MonkeyPatchTrait.php) in your TestCase class.### Convert `exit()` to Exception
This patcher converts `exit()` or `die()` statements to exceptions on the fly.
If you have a controller like below:
~~~php
public function index()
{
$this->output
->set_status_header(200)
->set_content_type('application/json', 'utf-8')
->set_output(json_encode(['foo' => 'bar']))
->_display();
exit();
}
~~~A test case could be like this:
~~~php
public function test_index()
{
try {
$this->request('GET', 'welcome/index');
} catch (ExitException $e) {
$output = ob_get_clean();
}
$this->assertContains('{"foo":"bar"}', $output);
}
~~~### Patch Functions
This patcher allows replacement of global functions that can't be mocked by PHPUnit.
But it has a few limitations. Some functions can't be replaced and it might cause errors.
So by default we can replace only a dozen pre-defined functions in [FunctionPatcher](https://github.com/kenjis/monkey-patch/blob/a11e1f227234dadeae2460d29b9c8ca6e91c88de/src/Patcher/FunctionPatcher.php#L31-L49).
~~~php
public function test_index()
{
MonkeyPatch::patchFunction('mt_rand', 100, 'Welcome::index');
$output = $this->request('GET', 'welcome/index');
$this->assertContains('100', $output);
}
~~~`MonkeyPatch::patchFunction()` replaces PHP native function `mt_rand()` in `Welcome::index` method, and it will return `100` in the test method.
**Note:** If you call `MonkeyPatch::patchFunction()` without 3rd argument, all the functions (located in `include_paths` and not in `exclude_paths`) called in the test method will be replaced. So, for example, a function in your library code might be replaced, and it results in an unexpected outcome.
#### Change Return Value
You could change return value of patched function using PHP closure:
~~~php
MonkeyPatch::patchFunction(
'function_exists',
function ($function) {
if ($function === 'random_bytes') {
return true;
} elseif ($function === 'openssl_random_pseudo_bytes') {
return false;
} elseif ($function === 'mcrypt_create_iv') {
return false;
} else {
return __GO_TO_ORIG__;
}
},
Welcome::class
);
~~~#### Patch Other Functions
If you want to patch other functions, you can add them to [functions_to_patch](https://github.com/kenjis/monkey-patch/blob/a11e1f227234dadeae2460d29b9c8ca6e91c88de/src/bootstrap.php#L56-L59) in `MonkeyPatchManager::init()`.
But there are a few known limitations:
- Patched functions which have parameters called by reference don't work.
- You may see visibility errors if you pass non-public callbacks to patched functions. For example, you pass `[$this, 'method']` to `array_map()` and the `method()` method in the class is not public.### Patch Methods in User-defined Classes
This patcher allows replacement of methods in user-defined classes.
~~~php
public function test_index()
{
MonkeyPatch::patchMethod(
Category_model::class,
['get_category_list' => [(object) ['name' => 'Nothing']]]
);
$output = $this->request('GET', 'welcome/index');
$this->assertContains('Nothing', $output);
}
~~~`MonkeyPatch::patchMethod()` replaces `get_category_list()` method in `Category_model`, and it will return `[(object) ['name' => 'Nothing']]` in the test method.
### Patch Constants
This patcher allows replacement of constant value.
~~~php
public function test_index()
{
MonkeyPatch::patchConstant(
'ENVIRONMENT',
'development',
Welcome::class . '::index'
);$output = $this->request('GET', 'welcome/index');
$this->assertContains('development', $output);
}
~~~`MonkeyPatch::patchConstant()` replaces the return value of the constant `ENVIRONMENT` in `Welcome::index` method.
There are a few known limitations:
- Cannot patch constants that are used as default values in function arguments.
- Cannot patch constants that are used as default values in constant declarations.
- Cannot patch constants that are used as default values in property declarations.
- Cannot patch constants that are used as default values in static variable declarations.## Class Reference
See [ci-phpunit-test docs](https://github.com/kenjis/ci-phpunit-test/blob/3.x/docs/FunctionAndClassReference.md#class-monkeypatch).
## License
This package is licensed using the MIT License.
Please have a look at [`LICENSE`](LICENSE).