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
相关产品推荐
相关产品推荐

