Framework: Cache::lock() failed when using unit test

Created on 13 Jul 2019  路  5Comments  路  Source: laravel/framework

  • Laravel Version: 5.7.17
  • PHP Version: 7.2.8
  • Database Driver & Version:
    Redis phpredis

    Description:

For some API I use \Cache::lock, When calling those API endpoints in test environment, application is failing because of

[2019-07-14 01:19:01] testing.ERROR: Call to undefined method Illuminate\Cache\ArrayStore::lock() {"userId":1,"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to undefined method Illuminate\\Cache\\ArrayStore::lock() at /Users/clark/Desktop/Outsource/yizhantuan-backend/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:587)
[stacktrace]
#0 vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php(323): Illuminate\\Cache\\Repository->__call('lock', Array)
#1 vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(223): Illuminate\\Cache\\CacheManager->__call('lock', Array)

Steps To Reproduce:

  1. Using Laravel unit test to some API which used \Cache::lock()
   'redis' => [

        'client' => 'phpredis',

        'default' => [
            'persistent' => true,
            'read_timeout' => 60,
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

    ],

All 5 comments

https://laravel.com/docs/5.8/cache#atomic-locks

To utilize this feature, your application must be using the memcached, dynamodb, or redis cache driver as your application's default cache driver.

You are using array store.

The cache driver is set to array in the phpunit.xml

@koenhoeijmakers @bonzai Thanks for your reply.
So is there any possibility use atomic-locks in test environment with test drivers, such as ArrayStore, NullStore.

If you want you can either override the value in the phpunit.xml, or override it for the tests that need it by overriding your config cache driver.

Here are two solutions for this.

  1. https://github.com/laravel/framework/issues/28161#issuecomment-482568324
    but this is so clumsy
  2. use mock like this
    public function mockLock(){
        $stub=$this->getMockBuilder(RedisLock::class)
            ->disableOriginalConstructor()
            ->disableOriginalClone()
            ->disableArgumentCloning()
            ->disallowMockingUnknownTypes()
            ->getMock();
        $stub->method('get')->willReturn(true);
        Cache::shouldReceive('lock')
            ->once()
            ->andReturn($stub);
    }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

PhiloNL picture PhiloNL  路  3Comments

Fuzzyma picture Fuzzyma  路  3Comments

JamborJan picture JamborJan  路  3Comments

iivanov2 picture iivanov2  路  3Comments

YannPl picture YannPl  路  3Comments