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

Laravel测试Cache门面Mock报driver未实现错误及缓存测试问题

问题1:CacheManager::driver()无期望报错的原因及解决

该报错的核心原因是:Laravel的Cache Facade本质是CacheManager的静态代理,调用Facade上的缓存方法时,CacheManager会先调用driver()方法获取指定驱动的实例,再在驱动实例上执行对应缓存操作。你仅给has方法设置了期望,没有覆盖driver()方法的调用,因此会抛出未定义期望的异常。

官方标准解决方式是在Mock Cache时先定义driver方法的期望,返回Mock自身即可:

// 先定义driver方法的通用期望
Cache::shouldReceive('driver')
    ->andReturnSelf();

// 再定义你需要的缓存方法期望
Cache::shouldReceive('has')
    ->once()
    ->with('folders') // 注意你当前测试中写的缓存键是campaign_folders,和实际业务代码里的folders不一致,需要修正
    ->andReturn(false);

额外注意:你当前的测试将整个Logic类做了完整Mock,直接替换了fetchData方法的实现,因此Logic类内部的缓存读写逻辑完全不会执行,如果要验证缓存相关行为,需要改为对Logic做部分Mock,或者只MockLogic依赖的外部接口,保留fetchData的真实执行逻辑。

问题2:验证二次请求走缓存的测试实现

你不需要操作真实缓存、清理缓存,该场景可以直接通过定义缓存方法的调用顺序期望实现,测试示例如下:

public function test_it_uses_cache_on_second_request()
{
    $mockedFoldersData = [/* 你模拟的getFolders返回数据 */];
    $mockedFinalResponse = [/* 你预期的fetchData返回结构 */];
    $route = '你的路由地址';

    // 定义driver方法通用期望
    Cache::shouldReceive('driver')->andReturnSelf();
    // 按调用顺序定义缓存期望
    Cache::shouldReceive('has')
        ->twice()
        ->with('folders')
        ->andReturn(false, true); // 第一次调用返回false,第二次返回true
    Cache::shouldReceive('put')
        ->once()
        ->with('folders', $mockedFinalResponse, 3600);
    Cache::shouldReceive('get')
        ->once()
        ->with('folders')
        ->andReturn($mockedFinalResponse);

    // 对Logic做部分Mock,仅替换getFolders方法,保留fetchData真实逻辑
    $this->instance(
        Logic::class,
        Mockery::mock(Logic::class)->makePartial()
            ->shouldReceive('getFolders')
            ->once()
            ->andReturn($mockedFoldersData)
            ->getMock()
    );

    // 第一次请求:缓存不存在,生成缓存
    $response1 = $this->httpGet($route);
    $response1->assertOk();
    // 第二次请求:缓存存在,直接读缓存
    $response2 = $this->httpGet($route);
    $response2->assertOk();

    // 两次返回结果一致
    $this->assertEquals($mockedFinalResponse, $response1->json());
    $this->assertEquals($mockedFinalResponse, $response2->json());
}

你提到的官方文档示例无法直接生效的原因是部分Laravel小版本中CacheManager的调用逻辑有调整,文档示例默认省略了driver方法的期望声明,上述方案为Laravel官方推荐的标准Mock写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:06:03