Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache::spy returns an exception: Trying to access array offset on value of type null #41721

Closed
FrancisMawn opened this issue Mar 28, 2022 · 2 comments

Comments

@FrancisMawn
Copy link
Contributor

  • Laravel Version: 9.5.1
  • PHP Version: 8.0.16
  • Database Driver & Version: MySQL 8

Description:

I'm not sure why but when I'm trying to make use of Cache::spy, I'm getting this exception:
Trying to access array offset on value of type null

Steps To Reproduce:

The issue can be reproduced with a fresh install:

web.php

Route::get('/', function () {
    $key = Cache::get('test-key');
    return view('welcome');
});

ExampleTest.php

public function test_cache()
{
    Cache::spy();

    $this->get('/')->assertStatus(200);

    Cache::shouldHaveReceived('get')->with('test-key')->once();
}

If you remove the assertStatus(200), the test passes as expected, otherwise the exception is thrown.

@derekmd
Copy link
Contributor

derekmd commented Mar 28, 2022

Unfortunately Cache::spy() and Cache::get() can't be mixed due to how the Mockery package proxies the spied CacheManager instance. It causes the wrong CacheManager method to be called.

protected function get($name)
{
return $this->stores[$name] ?? $this->resolve($name);
}

public function __call($method, $parameters)
{
return $this->store()->$method(...$parameters);
}

Cache::get('test-key') call stack:

  1. Illuminate\Support\Facades\Cache::get('test-key')
  2. Illuminate\Support\Facades\Facade::__callStatic('get', ['test-key'])
    • Without Mockery spy:
      • Illuminate\Cache\CacheManager::__call('get', ['test-key'])
      • Illuminate\Contracts\Cache\Repository::get('test-key') ✔️
    • With Mockery spy
      • Illuminate\Cache\CacheManager::get('test-key') (protected)

So the Mockery spy is allowing protected method CacheManager@get() to be externally invoked when the real world scenario accesses the cache store (Redis, etc.) through CacheManager@__call() -> CacheManager@store()->get().


You likely need to change this to a regular shouldReceive() mock setup:

Cache::shouldReceive('get')
    ->once()
    ->with('test-key')
    ->andReturn('foo');

$this->get('/')->assertStatus(200);

@driesvints
Copy link
Member

Thanks @derekmd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants