模拟 laravel 缓存助手

Posted

技术标签:

【中文标题】模拟 laravel 缓存助手【英文标题】:Mocking laravel cache helper 【发布时间】:2020-10-12 05:04:41 【问题描述】:

使用PESTphp testing framework,我想模拟 Laravel 的缓存助手,但是当我尝试它时,我收到如下错误:

Method Mockery_2_Illuminate_Cache_CacheManager::remember() does not exist on this mock object`

我想模拟rememberForever() 方法,但为什么remember() 方法会显示在错误消息中?我还尝试将shouldReceive() 更改为另一种方法,但总是remember() 方法被嘲笑。

这是我的控制器代码:

public function index()

    $groups = cache()->rememberForever('groups', fn() => Group::pluck('id', 'slug'));

    return view('index', compact(
        'groups'
    ));

和我的测试:

it('should return given data on index page', function () 
    /** @var \Tests\TestCase $this */

    $groups = Group::pluck('id', 'slug');

    Cache::shouldReceive('rememberForever')->once()
        ->with('groups', \Closure::class)
        ->andReturn($groups);

    actingAs()->get(route('index'))
        ->assertViewHasAll([
            'groups' => $groups,
        ]);
);

这是显示的错误:

 • it should return given data on index page

  ---


   Mockery\Exception\BadMethodCallException 

  Method Mockery_2_Illuminate_Cache_CacheManager::remember() does not exist on this mock object

  at D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\vendor\mockery\mockery\library\Mockery\Loader\EvalLoader.php:34
     30▕         if (class_exists($definition->getClassName(), false)) 
     31▕             return;
     32▕         
     33▕
  ➜  34▕         eval("?>" . $definition->getCode());
     35▕     
     36▕ 
     37▕

  1   D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\vendor\mockery\mockery\library\Mockery\Loader\EvalLoader.php:34
      Mockery_2_Illuminate_Cache_CacheManager::_mockery_handleMethodCall("remember")

  2   D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\database\factories\UserFactory.php:24
      Mockery_2_Illuminate_Cache_CacheManager::__call("remember")


  Tests:  1 failed
  Time:   10.12s

当使用 partialMock 时:

  • it should return given data on index page

  ---

   ErrorException 

  Trying to access array offset on value of type null

  at D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\vendor\laravel\framework\src\Illuminate\Cache\CacheManager.php:327
    323▕      * @return string
    324▕      */
    325▕     public function getDefaultDriver()
    326▕     
  ➜ 327▕         return $this->app['config']['cache.default'];
    328▕     
    329▕
    330▕     /**
    331▕      * Set the default cache driver name.

  1   D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\vendor\laravel\framework\src\Illuminate\Cache\CacheManager.php:327
      Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Trying to access array offset on value of type null", "D:\Projects\Framework\laravel\Kuhaku\Kuha
ku-Web\vendor\laravel\framework\src\Illuminate\Cache\CacheManager.php", [])

  2   D:\Projects\Framework\laravel\Kuhaku\Kuhaku-Web\vendor\mockery\mockery\library\Mockery\Loader\EvalLoader.php:34
      Illuminate\Cache\CacheManager::getDefaultDriver()


  Tests:  1 failed
  Time:   5.47s

【问题讨论】:

我想查看您的错误的完整堆栈跟踪?这可能是您在另一个上下文中使用缓存的方式有问题。您可以尝试像这样模拟它,如果可行的话 Cache::partialMock()->shouldReceive() 你试过用Cache门面代替助手吗? Cache::rememberForever(...)。这不是解决方案,但我想知道这是否解决了问题 我更新了完整的堆栈跟踪..并且没有存储错误日志我也启用了调试模式..我尝试使用外观而不是助手,部分模拟也给出了错误..在我使用 PEST 之前它工作正常。我不知道为什么... 所提供的答案是否有帮助?如果您有这样做的声誉,您应该用 ▲ 所有答案 支持。然后,您应该标记接受 ✓ 最能回答您的问题的一个答案。 This will mark the question as "closed," and give you some reputation on the site。如果没有一个答案令人满意,请向 cmets 提供反馈,或编辑您的问题以澄清问题。 【参考方案1】:

rememberForever 方法在您使用 cache() 帮助器或 Cache 外观获得的 CacheManager 实例上不存在。相反,它位于CacheRespository 实例上,您可以使用Mockery::spy() 进行观察,以确保调用正确的方法。

public function testCacheWorks(): void

    $cacheRepository = Cache::driver();
    $cacheRepositorySpy = \Mockery::spy($cacheRepository);
    Cache::swap($cacheRepositorySpy);

    // do stuff that writes to the cache

    $cacheRepositorySpy->shouldHaveReceived("rememberForever")
        ->once()
        ->with($cache_entry_key, \Closure::class)
        ->andReturns($some_test_object);

从这里挑选的:https://github.com/laravel/framework/issues/10803#issuecomment-625261817

【讨论】:

以上是关于模拟 laravel 缓存助手的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Laravel 正确模拟 Illuminate\Http\Request 类

无法在 laravel 6 中模拟任何自定义类方法

Laravel - 如何调用模型类助手然后在视图中显示结果

未找到 Laravel 助手类

未设置Laravel配置助手

Laravel 的加密和解密助手有多安全?