你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

thinkphp5集成phpunit6.5

2022/6/28 23:55:02

前言

tp5自带了phpunit,但是,其phpunit版本很老,有时候集成还会出错,反正我是集成之后没法用的,并且我又习惯了phpunit6.5的语法,所以在项目中想使用tp5集成phpunit 6.5,而不是用用tp默认的单元测试工具。

问题

tp5集成了phpunit后,最大的问题是类的自动加载问题。通常我们会在项目的extend目录下写一些自己的类库,但是在单元测试的时候会报类找不到。

namespace util;


class ConfigMap
{
    // 车辆配置
    const  CONFIGS = [
        // 车辆类型
        'viche_type' => [
            '1' => '栏板车',
            '2' => '高栏车'
        ]
    ];

    /**
     * 获取配置
     * @param $keys string 键, 传空值,表示获取对应type下的所有配置,多个用逗号隔开
     */
    public static function getConfs($names = '')
    {
        // TODO
    }
}

如上,在extend的util目录下,有个ConfigMap类,这个类很简单,就是配置一些数据,通过getConfs方法可以获取配置数据。

我想对此类写单元测试,在项目根目录下写一个phpunit.xml文件,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./application</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>

bootstrap选项用于引入自动加载的文件,利于我们通过命名空间自动加载类库。

然后在tests目录下编写单元测试。

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use util\ConfigMap;

class ConfigMapTest extends TestCase
{
    /**
     * 测试getConfs方法
     * @covers \util\ConfigMap::getConfs
     */
    public function testGetConfs()
    {
        $config_origin = ConfigMap::CONFIGS;
        $config = ConfigMap::getConfs();

        $this->assertEquals($config_origin, $config);
    }
}

在项目根目录运行单元测试,如下:

 ./vendor/bin/phpunit -c phpunit.xml tests/Unit/ConfigMapTest.php

结果会报错:

报错的原因在于thinkphp实现了一套自己的自动加载规则,它可以自动加载composer下定义的类库,也可以加载extend下的自定义类库。但是vendor/autoload.php无法加载extend目录下自定义的类库,所以,我自定义了一个自动加载文件,放在tests目录下,名称为autoloader.php

define('THINK_VERSION', '5.0.24');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS . '..' . DS . 'thinkphp' . DS);
define('LIB_PATH', THINK_PATH . 'library' . DS);
define('CORE_PATH', LIB_PATH . 'think' . DS);
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
defined('APP_PATH') or define('APP_PATH', THINK_PATH . '..' . DS . 'application' . DS);
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
//var_dump(CONF_PATH);exit;
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀

// 环境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);

// 载入Loader类
require CORE_PATH . 'Loader.php';

// 注册自动加载
\think\Loader::register();

// 初始化,加载函数等
\think\App::initCommon();

然后在phpunit.xml中使用此文件,如下:

这样,就可以使用我们自定义的自动加载规则了。

但是,运行后依然报错,原因是composer下的autoload_static.php重复引用了,如下:

改造一下think\Loader.php,将290行的require改为require_once,如下:

再次运行刚才的命令,单元测试就跑起来了: