diff --git a/src/Symfony/Contracts/Cache/GetForCacheItemPoolTrait.php b/src/Symfony/Contracts/Cache/GetForCacheItemPoolTrait.php index 8e8e514aef..6e868c309f 100644 --- a/src/Symfony/Contracts/Cache/GetForCacheItemPoolTrait.php +++ b/src/Symfony/Contracts/Cache/GetForCacheItemPoolTrait.php @@ -36,6 +36,7 @@ trait GetForCacheItemPoolTrait if (INF === $beta || !$item->isHit()) { $value = $callback($item); $item->set($value); + $this->save($item); } return $item->get(); diff --git a/src/Symfony/Contracts/Tests/Cache/GetForCacheItemPoolTraitTest.php b/src/Symfony/Contracts/Tests/Cache/GetForCacheItemPoolTraitTest.php new file mode 100644 index 0000000000..39f62d36d9 --- /dev/null +++ b/src/Symfony/Contracts/Tests/Cache/GetForCacheItemPoolTraitTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Tests\Cache; + +use PHPUnit\Framework\TestCase; +use Psr\Cache\CacheItemInterface; +use Symfony\Contracts\Cache\GetForCacheItemPoolTrait; + +/** + * @author Tobias Nyholm + */ +class GetForCacheItemPoolTraitTest extends TestCase +{ + public function testSave() + { + $item = $this->getMockBuilder(CacheItemInterface::class)->getMock(); + $item->method('isHit') + ->willReturn(false); + + $item->expects($this->once()) + ->method('set') + ->with('computed data'); + + $cache = $this->getMockBuilder(ClassUsingTrait::class) + ->setMethods(array('getItem', 'save')) + ->getMock(); + $cache->expects($this->once()) + ->method('getItem') + ->with('key') + ->willReturn($item); + $cache->expects($this->once()) + ->method('save'); + + $callback = function (CacheItemInterface $item) { + return 'computed data'; + }; + + $cache->get('key', $callback); + } + + public function testNoCallbackCallOnHit() + { + $item = $this->getMockBuilder(CacheItemInterface::class)->getMock(); + $item->method('isHit') + ->willReturn(true); + + $item->expects($this->never()) + ->method('set'); + + $cache = $this->getMockBuilder(ClassUsingTrait::class) + ->setMethods(array('getItem', 'save')) + ->getMock(); + + $cache->expects($this->once()) + ->method('getItem') + ->with('key') + ->willReturn($item); + $cache->expects($this->never()) + ->method('save'); + + $callback = function (CacheItemInterface $item) { + $this->assertTrue(false, 'This code should never be reached'); + }; + + $cache->get('key', $callback); + } + + public function testRecomputeOnBetaInf() + { + $item = $this->getMockBuilder(CacheItemInterface::class)->getMock(); + $item->method('isHit') + // We want to recompute even if it is a hit + ->willReturn(true); + + $item->expects($this->once()) + ->method('set') + ->with('computed data'); + + $cache = $this->getMockBuilder(ClassUsingTrait::class) + ->setMethods(array('getItem', 'save')) + ->getMock(); + + $cache->expects($this->once()) + ->method('getItem') + ->with('key') + ->willReturn($item); + $cache->expects($this->once()) + ->method('save'); + + $callback = function (CacheItemInterface $item) { + return 'computed data'; + }; + + $cache->get('key', $callback, INF); + } + + public function testExceptionOnNegativeBeta() + { + $cache = $this->getMockBuilder(ClassUsingTrait::class) + ->setMethods(array('getItem', 'save')) + ->getMock(); + + $callback = function (CacheItemInterface $item) { + return 'computed data'; + }; + + $this->expectException(\InvalidArgumentException::class); + $cache->get('key', $callback, -2); + } +} + +class ClassUsingTrait +{ + use GetForCacheItemPoolTrait; + + public function getItem($key) + { + } + + public function save(CacheItemInterface $item) + { + } +} diff --git a/src/Symfony/Contracts/composer.json b/src/Symfony/Contracts/composer.json index eb7b454ee6..c0c32b6f8f 100644 --- a/src/Symfony/Contracts/composer.json +++ b/src/Symfony/Contracts/composer.json @@ -19,6 +19,7 @@ "php": "^7.1.3" }, "require-dev": { + "psr/cache": "^1.0", "psr/container": "^1.0" }, "suggest": {