adriansuter / php-autoload-override
在您的类方法中覆盖全局作用域的完全限定函数调用,以便在测试期间对其进行模拟。
Requires
- php: ^7.3 || ^8.0
- nikic/php-parser: ^4.4
Requires (Dev)
- phpspec/prophecy-phpunit: ^2.0
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
This package is auto-updated.
Last update: 2024-09-09 12:40:46 UTC
README
此库允许覆盖类方法内的完全限定函数调用,以便在测试期间对其进行模拟。
注意:该库也可以用于其他场景,但我们建议仅用于测试目的。
要求
- PHP 7.3 或更高版本
- Composer with PSR-4(不支持 PSR-0)
安装
$ composer require --dev adriansuter/php-autoload-override 1.0
与 PHPUnit 一起使用
假设我们要对以下类进行单元测试 Probability
。
namespace My\App; class Probability { public function pick(int $probability, string $color1, string $color2): string { if (\rand(1, 100) <= $probability) { return $color1; } else { return $color2; } } }
该类有一个名为 pick
的方法,该方法接收一个概率(介于 0 和 100 之间)和两个颜色名称作为参数。然后该方法将使用全局作用域中的 rand
函数生成一个随机数,如果生成的数字小于等于给定的概率,则该方法将返回第一个颜色,否则将返回第二个颜色。
问题
由于我们无法控制 rand
函数的输出(它位于全局作用域中),因此我们无法对该方法进行单元测试。嗯,直到现在。使用 PHP-Autoload-Override 库,可以覆盖 rand
函数并因此控制其生成的随机数。
解决方案
安装 PHP-Autoload-Override 库后,我们打开测试套件的引导脚本(另请参阅 PHPUnit 配置)。在那里我们将编写以下代码
// tests/bootstrap.php /** @var \Composer\Autoload\ClassLoader $classLoader */ $classLoader = require_once __DIR__ . '/../vendor/autoload.php'; \AdrianSuter\Autoload\Override\Override::apply($classLoader, [ \My\App\Probability::class => [ 'rand' => function ($min, $max): int { if (isset($GLOBALS['rand_return'])) { return $GLOBALS['rand_return']; } return \rand($min, $max); } ] ]);
现在,类 Probability
将被加载到 PHPUnit 运行时中,使得类 Probability
中对全局作用域中的 rand()
函数的所有函数调用都由上面的闭包覆盖。
我们的测试类现在可以写成如下所示。
namespace My\App\Tests; use My\App\Probability; use PHPUnit\Framework\TestCase; final class ProbabilityTest extends TestCase { protected function tearDown() { if (isset($GLOBALS['rand_return'])) { unset($GLOBALS['rand_return']); } } public function testPick() { $p = new Probability(); $GLOBALS['rand_return'] = 35; $this->assertEquals('blue', $p->pick(34, 'red', 'blue')); $this->assertEquals('red', $p->pick(35, 'red', 'blue')); } }
测试用例 testPick
会调用两次 pick
方法。由于我们覆盖了 \rand
函数,我们可以控制其返回值始终为 35。因此,第一次调用检查 else
块是否执行。第二次调用检查 if
块是否执行。太好了,100% 代码覆盖率。
请注意,此覆盖仅在单元测试期间应用。
了解更多信息
许可证
PHP-Autoload-Override 库采用 MIT 许可证授权。有关更多信息,请参阅 许可证文件。