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

PhpUnit单元测试中如何伪造时间过期的文件?

问题根因与解决方案

你遇到的问题和Alpine Linux本身无关,是两个PHP和文件属性的特性导致的:

  • 你业务代码中调用的filectime()获取的是inode变更时间,不是文件内容修改时间。当你用touch命令修改文件的访问时间、修改时间时,会触发inode元数据变更,ctime会自动被系统更新为当前时间,所以你读取到的filectime永远是当前操作的时间,不是你设置的历史时间。
  • PHP默认开启了文件状态缓存,所有stat系列函数(包括filectime、filemtime、file_exists等)的返回值都会被缓存,你修改完文件属性后如果不清理缓存,读取到的还是之前缓存的旧值。

修复方案

方案1:适配业务逻辑+清理缓存

如果你的业务逻辑实际需要判断的是文件内容是否超过1天未修改,将业务代码中的filectime替换为filemtime,filemtime获取的是文件内容修改时间,也就是touch -m参数修改的时间。
修改测试代码,每次操作文件前后清理指定文件的状态缓存:

$location = '/var/www/var/xls/myfile.xlsx';
$handle = fopen($location, 'wb');
fclose($handle);
// 清理文件状态缓存,避免残留旧数据
clearstatcache(true, $location);
// 注意用escapeshellarg转义路径,避免安全问题
exec('touch -m -t 202109231158 ' . escapeshellarg($location));
// 再次清理缓存,确保读取到最新属性
clearstatcache(true, $location);

// 此时读取filemtime即可拿到设置的2021-09-23时间
var_dump(date('Ymd', filemtime($location)));

方案2:单元测试直接mock时间函数

不需要创建实际文件,用PHPUnit的函数mock功能或者uopz扩展直接mockfilectime/filemtime的返回值,测试更轻量,也不会受文件系统特性影响。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:54:04