Laravel模拟2个单独的Cache ::记得在同一个测试中

I am writing a test for a console command. In the command we make 2 separate api calls to external services which I can mock fine. But both of those external calls are wrapped in Cache::remember. I want to able to mock both of those Caches in my test, but can't seem to figure it out. I can only seem to mock the first one. They have different keys.

So for example, my console command has something like this (which I have simplified for the this)

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();
});

In my test, I want one of the Caches to return null, and the other to return a mocked object.

Here is the first one.

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

If I out put the second one in

$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));

it sill returns null.

How can I mock the second Cache please.

You can use ->once() for such purposes.

// 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));

OK, this was me being a bit silly but after a few hours staring at the code and the docs I figured this out.

In my example I don't need to mock the Caches, since the methods inside the Caches are already mocked. Plus I wasn't returning any value from the Cache methods.

In my command, the Cache::remember blocks are in there own method, but I wasnt returning anything.

So this

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();
    });
}

got updated to this

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();
    });
}

In my test I just Cache::flush(); and continue with the mocked classes I already had in place.