You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对包含多类依赖的PHP非类CLI运行函数进行单元测试

PHP CLI常驻脚本单元测试可行方案

针对你提供的常驻CLI脚本,可按照以下两个维度的方案实现测试,同时完成所有外部依赖的Mock:

最小侵入式测试方案(无需大规模修改原有代码)

适合暂时无法重构原有业务代码的场景,改动量极小:

  • 第一步先封装脚本执行入口,避免文件加载即执行:在原有脚本最外层增加执行判断,把所有业务逻辑包裹到独立函数内
    // 原有run_task.php文件头部新增代码
    if (!defined('RUN_TASK_TEST_MODE')) {
        runTaskEntry();
    }
    
    function runTaskEntry() {
        // 把你原有全部脚本代码放到该函数内
    }
    
    测试时提前定义RUN_TASK_TEST_MODE常量,引入文件后可自主调用执行逻辑,不会触发自动运行。
  • 单例类Mock:通过反射替换单例类的私有实例属性,无需修改单例原有代码即可注入Mock对象,示例如下:
    // 以Mock settings单例为例
    $mockSettings = $this->createMock(settings::class);
    $mockSettings->expects($this->once())->method('load')->with('main');
    // 反射修改单例实例
    $ref = new ReflectionClass(settings::class);
    $instanceProp = $ref->getProperty('instance');
    $instanceProp->setAccessible(true);
    $instanceProp->setValue(null, $mockSettings);
    
    按照同样逻辑完成db、mongo、\publish\Log、\publish\JobEngine等所有依赖的Mock。
  • 无限循环规避:用命名空间函数覆盖的方式替换原生usleep实现,同时可以在测试时临时修改循环计数阈值,比如将1000次退出改为2次退出,避免测试死循环。
  • 逻辑验证点覆盖:
    • 信号处理:手动调用gracefullExit函数,验证GRACEFULL_EXIT环境变量被正确设置为1,脚本可正常退出且退出码为0
    • 异常捕获:Mock\publish\JobEngine::runTask()使其抛出异常,验证异常被捕获,不会终止脚本运行,error_log有对应错误输出
    • 自动重启:验证循环次数达到阈值后脚本正常退出

可测试性重构方案(长期维护推荐)

如果允许调整原有代码,重构后测试成本会大幅降低:

  • 把所有逻辑拆分到独立的RunTask类中,初始化、信号处理、主循环分别封装为独立方法
  • 所有外部依赖(settings、db、mongo、日志、任务引擎)全部通过构造函数注入,替换原有硬编码的单例调用、静态调用
  • 把usleep、getenv、putenv等系统调用也封装为可注入的工具类,测试时直接Mock工具类即可,无需处理全局函数覆盖

重构完成后测试时直接传入所有Mock后的依赖对象即可,测试用例编写更简单,可维护性更高。

内容的提问来源于stack exchange,提问作者banshee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 15:09:03