The motivation is simple: when unit testing a class that depends on cache, you either need to mock the storage and
go through Cache
code to find what methods are called upon the storage, or use some wibbly wobbly
autoloading magic. I don’t think either
way is a good one to go.
The thing is really straight-forward with Oops/CacheFactory. You can get it going in just two steps. First, install it via Composer:
$ composer require oops/cache-factory:~1.0
Second, register the extension in your config:
extensions:
cacheFactory: Oops\CacheFactory\DI\CacheFactoryExtension
That’s pretty much it. Now you can replace occurrences of direct Cache
instantiation with call to the factory,
so that this:
class CachedFoo
{
private $cache;
public function __construct(Nette\Caching\IStorage $cacheStorage)
{
$this->cache = new Nette\Caching\Cache($cacheStorage, 'namespace');
}
}
becomes this:
class CachedFoo
{
private $cache;
public function __construct(Oops\CacheFactory\Caching\CacheFactory $cacheFactory)
{
$this->cache = $cacheFactory->create('namespace');
}
}
The factory automatically uses the storage registered in the config. To provide backwards compatibility, you can also pass to the factory an arbitrary storage, should you need it:
$cacheFactory->create('namespace', new Nette\Caching\Storages\DevNullStorage());
Notice how it streamlined mocking cache as a dependency in unit tests:
$cacheMock = \Mockery::mock('Nette\Caching\Cache');
$cacheMock->shouldReceive('load')->once()->andReturnNull();
// other expectations
$cacheFactoryMock = \Mockery::mock('Oops\CacheFactory\Caching\CacheFactory');
$cacheFactoryMock->shouldReceive('create')
->with('namespace')
->andReturn($cacheMock);
$foo = new CachedFoo($cacheFactoryMock);
Handy, isn’t it?