avris/function-mock

用于模拟全局函数的轻量级类

v1.0.1 2018-01-09 20:28 UTC

This package is auto-updated.

Last update: 2024-09-12 04:10:48 UTC


README

FunctionMock 是一个简单优雅的方式来在测试中模拟系统/全局函数。

安装

composer require --dev avris/function-mock

用法

假设你有一个将内容写入文件的类

<?php
namespace App\Service;
    
class WorkService
{
    public function work(int $input): bool
    {
        $result = 'correctResult'; // ... calculate the result somehow
        
        $filename = '/tmp/foo';
        
        return file_put_contents($filename, $result);
    }
}

为了测试它,而不实际使用文件系统,你可以使用 FunctionMock

<?php
namespace App\Test;
    
use App\Service\WorkService
use PHPUnit\Framework\TestCase;
    
class ServiceTest extends TestCase
{
    /** @var WorkService */
    private $service;
    
    protected function setUp()
    {
        $this->service = new WorkService();
    }
    
    protected function tearDown()
    {
        FunctionMock::clean();
    }
    
    public function testWork()
    {
        $mock = FunctionMock::create('App', 'file_put_contents', true);
        
        $returnValue = $this->service->work(8);
        
        $this->assertTrue($returnValue);
        $this->assertEquals([['/tmp/foo', 'correctResult']], $mock->getInvocations());
    }
}

如果你的测试与被测试类在同一命名空间中,建议使用 __NAMESPACE__

第三个参数,模拟函数的返回值,可以是字面量或可调用对象

$mock = FunctionMock::create(__NAMESPACE__, 'file_put_contents', function ($filename, $data) {
    return $filename === '/tmp/foo';
});

你可以通过调用 $mock->disable()$mock->enable() 来禁用/启用模拟,以及通过 $mock->clearInvocations() 清除记录的调用列表。

已知限制

FunctionMock 是通过 file_get_contentsApp\Service 命名空间内引用函数 App\Service\file_get_contents 并仅在它未定义时回退到全局 \file_get_contents 来工作的。

FunctionMock 会动态定义这个 App\Service\file_get_contents 函数,并使其在运行时可根据你的需求进行调整。

  • 如果你在注册模拟之前已经在 App\Service 内调用了 file_get_contents,PHP 将继续使用全局函数,并且不能再被覆盖。
  • 如果你在测试类中使用了 \file_get_contents(显式全局命名空间),显然无法对其进行模拟。
  • 注册后,模拟函数实际上不能被真正删除,只能被禁用。

版权