【问题标题】:Laravel mock 2 separate Cache::remember in same testLaravel 模拟 2 个单独的 Cache::remember 在同一个测试中
【发布时间】:2019-12-14 20:39:18
【问题描述】:

我正在为控制台命令编写测试。在命令中,我们对外部服务进行了 2 次单独的 api 调用,我可以很好地模拟它们。但是这两个外部调用都包含在Cache::remember 中。我希望能够在我的测试中模拟这两个缓存,但似乎无法弄清楚。我似乎只能嘲笑第一个。它们有不同的键。

例如,我的控制台命令有这样的东西(我已经为此简化了)

Cache::remember("key-1", (60 * 60) * 24, function () use ($variable) {
    return $this->externalApiAdapter->makeApiCall($variable);
});

Cache::remember("key-2", (60 * 60) * 24, function () {
    return $this->secondExternalApiAdapter->makeAnotherApiCall();
});

在我的测试中,我希望一个缓存返回null,另一个返回一个模拟对象。

这是第一个。

Cache::shouldReceive('remember')
    ->with('key-1', (60 * 60) * 24, \Closure::class)
    ->andReturn(null);

如果我把第二个放进去

$mockedObject = json_encode([
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
]);

Cache::shouldReceive('remember')
    ->with('key-2', (60 * 60) * 24, \Closure::class)
    ->andReturn((object)json_decode($mockedObject));

它仍然返回 null。

请问如何模拟第二个缓存。

【问题讨论】:

    标签: php laravel caching mocking phpunit


    【解决方案1】:

    好的,这是我有点傻,但在盯着代码和文档几个小时后,我发现了这一点。

    在我的示例中,我不需要模拟缓存,因为缓存中的方法已经被模拟了。另外,我没有从 Cache 方法返回任何值。

    在我的命令中,Cache::remember 块有自己的方法,但我没有返回任何东西。

    所以这个

    public function methodOne ()
    {
        Cache::remember("key-1", (60 * 60) * 24, function () use ($variable) {
            return $this->externalApiAdapter->makeApiCall($variable);
        });
    }
    public function methodTwo ()
    {
        Cache::remember("key-2", (60 * 60) * 24, function () {
            return $this->secondExternalApiAdapter->makeAnotherApiCall();
        });
    }
    

    更新到这个

    public function methodOne ()
    {
        return Cache::remember("key-1", (60 * 60) * 24, function () use ($variable) {
            return $this->externalApiAdapter->makeApiCall($variable);
        });
    }
    public function methodTwo ()
    {
        return Cache::remember("key-2", (60 * 60) * 24, function () {
            return $this->secondExternalApiAdapter->makeAnotherApiCall();
        });
    }
    

    在我的测试中,我只是 Cache::flush(); 并继续使用我已有的模拟类。

    【讨论】:

      【解决方案2】:

      您可以将->once() 用于此类目的。

      // This will be returned the first time Cache::remember is called
      Cache::shouldReceive('remember')
          ->once()
          ->with('key-1', (60 * 60) * 24, \Closure::class)
          ->andReturn(null);
      
      $mockedObject = json_encode([
          'key1' => 'value1',
          'key2' => 'value2',
          'key3' => 'value3'
      ]);
      
      // This will be returned the second time Cache::remember is called
      Cache::shouldReceive('remember')
          ->once()
          ->with('key-2', (60 * 60) * 24, \Closure::class)
          ->andReturn((object)json_decode($mockedObject));
      

      【讨论】:

      • 您确定在执行您的代码之前没有完成其他Cache::remember 调用吗?
      • 是的,我确定。我只是在测试中运行一个命令$this-artisan('command-key');没有其他缓存发生。
      猜你喜欢
      • 2016-04-04
      • 2016-06-14
      • 1970-01-01
      • 2016-09-30
      • 2017-05-12
      • 2021-08-06
      • 1970-01-01
      • 2019-08-03
      • 2021-02-09
      相关资源
      最近更新 更多