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

Laravel Storage Fake测试生成文件无法自动删除问题与解决方案

Laravel Storage Faker 自动清理文件问题及解决方案

我在使用Laravel的Storage::fake()时遇到了相关问题,花费了不少时间才调试通代码,不过一开始我还没有完全理解Storage Faker的运行原理。

下方是我的可运行代码精简版:setUp方法会创建Storage模拟对象并生成一个文件,随后将该文件的路径存入数据库。
之后我调用了Repository层的一个函数来校验路径是否存在,该部分代码不便公开,不过这不影响问题说明,因为这部分功能运行正常 ;)

use WithoutMiddleware;
use DatabaseTransactions;

protected $file;

protected function setUp(): void
{
    parent::setUp();

    $path = 'protocols';

    Storage::fake($path);

    $this->file = UploadedFile::fake()->createWithContent(
        'protocol.html',
        'Import gestartet am: 03.09.2019 10:54:13'
    )->store($path);

    factory(Protocol::class)->create([
        'partner_id' => 1,
        'user_id' => 1,
        'path' => $this->file
    ]);
}

/** @test */
public function path_exists()
{
    //Called function returns true

    $path_exists = functionCall('protocols/Test.pdf');
    $this->assertTrue($path_exists);

    $path_exists = functionCall('protocols/Test2.pdf');
    $this->assertTrue($path_exists);

    $path_exists = functionCall('protocols/Test3.pdf');
    $this->assertTrue($path_exists);
}

/** @test */
public function path_does_not_exist()
{
    //Called function throws an Exception

    $this->expectException(Exception::class);
    $this->expectExceptionMessage('file_not_found');
    $path_exists = functionCall('protocols/XY.pdf');

    $this->expectException(Exception::class);
    $this->expectExceptionMessage('file_not_found');
    $path_exists = functionCall('protocols/XY2.pdf');
}

protected function tearDown(): void
{
    Storage::delete($this->file);

    parent::tearDown();
}

到这里运行都正常,但是测试结束后我需要像tearDown方法中写的那样手动删除创建的文件。

这就引出了我的疑问:我看过很多帖子都提到Storage faker不会自动删除创建的文件,为什么会这样呢?既然我用了Storage模拟能力,为什么还需要测试结束后手动删文件?我实在想不通这一点。
还是说我理解有误,Storage Faker本身是可以实现自动删除生成的文件的?


解决方案

我将原本传入Storage::fake()的参数从protocols改成了local。protocols只是local磁盘下的一个路径,本身并不是独立配置的磁盘。
做完这个小改动后,我就可以删掉tearDown方法了,现在测试结束后系统会自动删除生成的文件。

修正后的完整代码:

use WithoutMiddleware;
use DatabaseTransactions;

protected $file;

protected function setUp(): void
{
    parent::setUp();

    $path = 'local';

    Storage::fake($path);

    $this->file = UploadedFile::fake()->createWithContent(
        'protocol.html',
        'Import gestartet am: 03.09.2019 10:54:13'
    )->store($path);

    factory(Protocol::class)->create([
        'partner_id' => 1,
        'user_id' => 1,
        'path' => $this->file
    ]);
}

/** @test */
public function path_exists()
{
    //Called function returns true

    $path_exists = functionCall('protocols/Test.pdf');
    $this->assertTrue($path_exists);

    $path_exists = functionCall('protocols/Test2.pdf');
    $this->assertTrue($path_exists);

    $path_exists = functionCall('protocols/Test3.pdf');
    $this->assertTrue($path_exists);
}

/** @test */
public function path_does_not_exist()
{
    //Called function throws an Exception

    $this->expectException(Exception::class);
    $this->expectExceptionMessage('file_not_found');
    $path_exists = functionCall('protocols/XY.pdf');

    $this->expectException(Exception::class);
    $this->expectExceptionMessage('file_not_found');
    $path_exists = functionCall('protocols/XY2.pdf');
}

原理说明

Storage::fake() 的入参必须是你在 config/filesystems.php 中配置的合法磁盘名称,而非子目录路径。调用该方法时,Laravel会自动将对应磁盘的存储根目录映射到系统临时目录的随机文件夹,PHP测试进程结束后,系统会自动清理临时目录下的所有文件,无需手动删除。
之前传入的protocols只是local磁盘下的子目录,不是独立配置的磁盘,所以fake机制没有生效,文件实际写入了本地真实存储路径,因此需要手动在tearDown中删除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 23:36:03