diff --git a/README.md b/README.md index 98be7a5..0bf684a 100644 --- a/README.md +++ b/README.md @@ -413,12 +413,6 @@ $connector = new React\Socket\Connector([ $redis = new Clue\React\Redis\RedisClient('localhost', $connector); ``` -This class takes an optional `LoopInterface|null $loop` parameter that can be used to -pass the event loop instance to use for this object. You can use a `null` value -here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). -This value SHOULD NOT be given unless you're sure you want to explicitly use a -given event loop instance. - #### __call() The `__call(string $name, string[] $args): PromiseInterface` method can be used to diff --git a/src/Io/Factory.php b/src/Io/Factory.php index a669793..196ee0d 100644 --- a/src/Io/Factory.php +++ b/src/Io/Factory.php @@ -4,7 +4,6 @@ use Clue\Redis\Protocol\Factory as ProtocolFactory; use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; use React\Promise\Deferred; use React\Promise\Promise; use React\Promise\PromiseInterface; @@ -18,9 +17,6 @@ */ class Factory { - /** @var LoopInterface */ - private $loop; - /** @var ConnectorInterface */ private $connector; @@ -28,14 +24,12 @@ class Factory private $protocol; /** - * @param ?LoopInterface $loop * @param ?ConnectorInterface $connector * @param ?ProtocolFactory $protocol */ - public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ProtocolFactory $protocol = null) + public function __construct(ConnectorInterface $connector = null, ProtocolFactory $protocol = null) { - $this->loop = $loop ?: Loop::get(); - $this->connector = $connector ?: new Connector([], $this->loop); + $this->connector = $connector ?: new Connector(); $this->protocol = $protocol ?: new ProtocolFactory(); } @@ -182,13 +176,13 @@ function (\Exception $e) use ($redis, $uri) { $timer = null; $promise = $promise->then(function (StreamingClient $v) use (&$timer, $resolve): void { if ($timer) { - $this->loop->cancelTimer($timer); + Loop::cancelTimer($timer); } $timer = false; $resolve($v); }, function (\Throwable $e) use (&$timer, $reject): void { if ($timer) { - $this->loop->cancelTimer($timer); + Loop::cancelTimer($timer); } $timer = false; $reject($e); @@ -200,7 +194,7 @@ function (\Exception $e) use ($redis, $uri) { } // start timeout timer which will cancel the pending promise - $timer = $this->loop->addTimer($timeout, function () use ($timeout, &$promise, $reject, $uri): void { + $timer = Loop::addTimer($timeout, function () use ($timeout, &$promise, $reject, $uri): void { $reject(new \RuntimeException( 'Connection to ' . $uri . ' timed out after ' . $timeout . ' seconds (ETIMEDOUT)', \defined('SOCKET_ETIMEDOUT') ? \SOCKET_ETIMEDOUT : 110 diff --git a/src/RedisClient.php b/src/RedisClient.php index f923d0f..1710d11 100644 --- a/src/RedisClient.php +++ b/src/RedisClient.php @@ -6,7 +6,6 @@ use Clue\React\Redis\Io\StreamingClient; use Evenement\EventEmitter; use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; use React\Promise\PromiseInterface; use React\Socket\ConnectorInterface; use React\Stream\Util; @@ -40,9 +39,6 @@ class RedisClient extends EventEmitter /** @var ?PromiseInterface */ private $promise = null; - /** @var LoopInterface */ - private $loop; - /** @var float */ private $idlePeriod = 0.001; @@ -58,12 +54,7 @@ class RedisClient extends EventEmitter /** @var array */ private $psubscribed = []; - /** - * @param string $url - * @param ?ConnectorInterface $connector - * @param ?LoopInterface $loop - */ - public function __construct($url, ConnectorInterface $connector = null, LoopInterface $loop = null) + public function __construct(string $url, ConnectorInterface $connector = null) { $args = []; \parse_str((string) \parse_url($url, \PHP_URL_QUERY), $args); @@ -72,8 +63,7 @@ public function __construct($url, ConnectorInterface $connector = null, LoopInte } $this->target = $url; - $this->loop = $loop ?: Loop::get(); - $this->factory = new Factory($this->loop, $connector); + $this->factory = new Factory($connector); } /** @@ -102,7 +92,7 @@ private function client(): PromiseInterface $this->subscribed = $this->psubscribed = []; if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::cancelTimer($this->idleTimer); $this->idleTimer = null; } }); @@ -235,7 +225,7 @@ public function close(): void } if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::cancelTimer($this->idleTimer); $this->idleTimer = null; } @@ -248,7 +238,7 @@ private function awake(): void ++$this->pending; if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::cancelTimer($this->idleTimer); $this->idleTimer = null; } } @@ -258,7 +248,7 @@ private function idle(): void --$this->pending; if ($this->pending < 1 && $this->idlePeriod >= 0 && !$this->subscribed && !$this->psubscribed && $this->promise !== null) { - $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () { + $this->idleTimer = Loop::addTimer($this->idlePeriod, function () { assert($this->promise instanceof PromiseInterface); $this->promise->then(function (StreamingClient $redis) { $redis->close(); diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index c1fe42b..25bf829 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -10,7 +10,6 @@ class FunctionalTest extends TestCase { - /** @var string */ private $uri; diff --git a/tests/Io/FactoryStreamingClientTest.php b/tests/Io/FactoryStreamingClientTest.php index 669b069..fbc274a 100644 --- a/tests/Io/FactoryStreamingClientTest.php +++ b/tests/Io/FactoryStreamingClientTest.php @@ -6,6 +6,7 @@ use Clue\React\Redis\Io\StreamingClient; use Clue\Tests\React\Redis\TestCase; use PHPUnit\Framework\MockObject\MockObject; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\EventLoop\TimerInterface; use React\Promise\Deferred; @@ -16,34 +17,31 @@ class FactoryStreamingClientTest extends TestCase { - /** @var MockObject */ - private $loop; - /** @var MockObject */ private $connector; /** @var Factory */ private $factory; - public function setUp(): void - { - $this->loop = $this->createMock(LoopInterface::class); - $this->connector = $this->createMock(ConnectorInterface::class); + /** @var LoopInterface */ + public static $loop; - assert($this->loop instanceof LoopInterface); - assert($this->connector instanceof ConnectorInterface); - $this->factory = new Factory($this->loop, $this->connector); + public static function setUpBeforeClass(): void + { + self::$loop = Loop::get(); } - public function testConstructWithoutLoopAssignsLoopAutomatically(): void + public static function tearDownAfterClass(): void { - $factory = new Factory(); + Loop::set(self::$loop); + } - $ref = new \ReflectionProperty($factory, 'loop'); - $ref->setAccessible(true); - $loop = $ref->getValue($factory); + public function setUp(): void + { + $this->connector = $this->createMock(ConnectorInterface::class); - $this->assertInstanceOf(LoopInterface::class, $loop); + assert($this->connector instanceof ConnectorInterface); + $this->factory = new Factory($this->connector); } /** @@ -51,8 +49,7 @@ public function testConstructWithoutLoopAssignsLoopAutomatically(): void */ public function testCtor(): void { - assert($this->loop instanceof LoopInterface); - $this->factory = new Factory($this->loop); + $this->factory = new Factory(); } public function testWillConnectWithDefaultPort(): void @@ -87,6 +84,11 @@ public function testWillWriteSelectCommandIfTargetContainsPath(): void $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $this->factory->createClient('redis://127.0.0.1/demo'); } @@ -96,6 +98,11 @@ public function testWillWriteSelectCommandIfTargetContainsDbQueryParameter(): vo $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$1\r\n4\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $this->factory->createClient('redis://127.0.0.1?db=4'); } @@ -105,6 +112,11 @@ public function testWillWriteAuthCommandIfRedisUriContainsUserInfo(): void $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://hello:world@example.com'); } @@ -114,6 +126,11 @@ public function testWillWriteAuthCommandIfRedisUriContainsEncodedUserInfo(): voi $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://:h%40llo@example.com'); } @@ -123,6 +140,11 @@ public function testWillWriteAuthCommandIfTargetContainsPasswordQueryParameter() $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$6\r\nsecret\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://example.com?password=secret'); } @@ -132,6 +154,11 @@ public function testWillWriteAuthCommandIfTargetContainsEncodedPasswordQueryPara $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://example.com?password=h%40llo'); } @@ -141,6 +168,11 @@ public function testWillWriteAuthCommandIfRedissUriContainsUserInfo(): void $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('tls://example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('rediss://hello:world@example.com'); } @@ -150,6 +182,11 @@ public function testWillWriteAuthCommandIfRedisUnixUriContainsPasswordQueryParam $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix:///tmp/redis.sock?password=world'); } @@ -168,6 +205,11 @@ public function testWillWriteAuthCommandIfRedisUnixUriContainsUserInfo(): void $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix://hello:world@/tmp/redis.sock'); } @@ -275,6 +317,11 @@ public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix:///tmp/redis.sock?db=demo'); } @@ -584,8 +631,12 @@ public function testCancelWillCloseConnectionWhenConnectionWaitsForSelect(): voi public function testCreateClientWithTimeoutParameterWillStartTimerAndRejectOnExplicitTimeout(): void { + $loop = $this->createMock(LoopInterface::class); + assert($loop instanceof LoopInterface); + Loop::set($loop); + $timeout = null; - $this->loop->expects($this->once())->method('addTimer')->with(0, $this->callback(function ($cb) use (&$timeout) { + $loop->expects($this->once())->method('addTimer')->with(0, $this->callback(function ($cb) use (&$timeout) { $timeout = $cb; return true; })); @@ -613,7 +664,11 @@ public function testCreateClientWithTimeoutParameterWillStartTimerAndRejectOnExp public function testCreateClientWithNegativeTimeoutParameterWillNotStartTimer(): void { - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + assert($loop instanceof LoopInterface); + Loop::set($loop); + + $loop->expects($this->never())->method('addTimer'); $deferred = new Deferred(); $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:2')->willReturn($deferred->promise()); @@ -623,7 +678,10 @@ public function testCreateClientWithNegativeTimeoutParameterWillNotStartTimer(): public function testCreateClientWithoutTimeoutParameterWillStartTimerWithDefaultTimeoutFromIni(): void { - $this->loop->expects($this->once())->method('addTimer')->with(42, $this->anything()); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer')->with(42, $this->anything()); + assert($loop instanceof LoopInterface); + Loop::set($loop); $deferred = new Deferred(); $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:2')->willReturn($deferred->promise()); @@ -637,9 +695,12 @@ public function testCreateClientWithoutTimeoutParameterWillStartTimerWithDefault public function testCreateClientWillCancelTimerWhenConnectionResolves(): void { + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $deferred = new Deferred(); $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:6379')->willReturn($deferred->promise()); @@ -652,9 +713,12 @@ public function testCreateClientWillCancelTimerWhenConnectionResolves(): void public function testCreateClientWillCancelTimerWhenConnectionRejects(): void { + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $deferred = new Deferred(); $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:6379')->willReturn($deferred->promise()); diff --git a/tests/RedisClientTest.php b/tests/RedisClientTest.php index 8fc8bab..6bfdb7e 100644 --- a/tests/RedisClientTest.php +++ b/tests/RedisClientTest.php @@ -6,6 +6,7 @@ use Clue\React\Redis\Io\Factory; use Clue\React\Redis\Io\StreamingClient; use PHPUnit\Framework\MockObject\MockObject; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\EventLoop\TimerInterface; use React\Promise\Deferred; @@ -16,19 +17,27 @@ class RedisClientTest extends TestCase /** @var MockObject */ private $factory; - /** @var MockObject */ - private $loop; - /** @var RedisClient */ private $redis; + /** @var Loopinterface */ + public static $loop; + + public static function setUpBeforeClass(): void + { + self::$loop = Loop::get(); + } + + public static function tearDownAfterClass(): void + { + Loop::set(self::$loop); + } + public function setUp(): void { $this->factory = $this->createMock(Factory::class); - $this->loop = $this->createMock(LoopInterface::class); - assert($this->loop instanceof LoopInterface); - $this->redis = new RedisClient('localhost', null, $this->loop); + $this->redis = new RedisClient('localhost'); $ref = new \ReflectionProperty($this->redis, 'factory'); $ref->setAccessible(true); @@ -40,7 +49,10 @@ public function testPingWillCreateUnderlyingClientAndReturnPendingPromise(): voi $promise = new Promise(function () { }); $this->factory->expects($this->once())->method('createClient')->willReturn($promise); - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->never())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->ping(); @@ -64,7 +76,10 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleT $deferred = new Deferred(); $this->factory->expects($this->once())->method('createClient')->willReturn($deferred->promise()); - $this->loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything()); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything()); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->ping(); $deferred->resolve($client); @@ -74,8 +89,7 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleT public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleTimerWithIdleTimeFromQueryParam(): void { - assert($this->loop instanceof LoopInterface); - $this->redis = new RedisClient('localhost?idle=10', null, $this->loop); + $this->redis = new RedisClient('localhost?idle=10'); $ref = new \ReflectionProperty($this->redis, 'factory'); $ref->setAccessible(true); @@ -87,7 +101,10 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleT $deferred = new Deferred(); $this->factory->expects($this->once())->method('createClient')->willReturn($deferred->promise()); - $this->loop->expects($this->once())->method('addTimer')->with(10.0, $this->anything()); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer')->with(10.0, $this->anything()); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->ping(); $deferred->resolve($client); @@ -97,8 +114,7 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleT public function testPingWillResolveWhenUnderlyingClientResolvesPingAndNotStartIdleTimerWhenIdleParamIsNegative(): void { - assert($this->loop instanceof LoopInterface); - $this->redis = new RedisClient('localhost?idle=-1', null, $this->loop); + $this->redis = new RedisClient('localhost?idle=-1'); $ref = new \ReflectionProperty($this->redis, 'factory'); $ref->setAccessible(true); @@ -110,7 +126,10 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndNotStartId $deferred = new Deferred(); $this->factory->expects($this->once())->method('createClient')->willReturn($deferred->promise()); - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->never())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->ping(); $deferred->resolve($client); @@ -127,7 +146,10 @@ public function testPingWillRejectWhenUnderlyingClientRejectsPingAndStartIdleTim $deferred = new Deferred(); $this->factory->expects($this->once())->method('createClient')->willReturn($deferred->promise()); - $this->loop->expects($this->once())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->ping(); $deferred->resolve($client); @@ -225,7 +247,10 @@ public function testPingAfterPingWillNotStartIdleTimerWhenFirstPingResolves(): v $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->never())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->ping(); $this->redis->ping(); @@ -243,9 +268,12 @@ public function testPingAfterPingWillStartAndCancelIdleTimerWhenSecondPingStarts $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->ping(); $deferred->resolve(null); @@ -260,12 +288,15 @@ public function testPingFollowedByIdleTimerWillCloseUnderlyingConnectionWithoutC $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); + $loop = $this->createMock(LoopInterface::class); $timeout = null; $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->with($this->anything(), $this->callback(function ($cb) use (&$timeout) { + $loop->expects($this->once())->method('addTimer')->with($this->anything(), $this->callback(function ($cb) use (&$timeout) { $timeout = $cb; return true; }))->willReturn($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->on('close', $this->expectCallableNever()); @@ -341,9 +372,12 @@ public function testCloseAfterPingWillCancelIdleTimerWhenPingIsAlreadyResolved() $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->ping(); $deferred->resolve(null); @@ -362,9 +396,12 @@ public function testCloseAfterPingRejectsWillEmitClose(): void $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->ping()->then(null, function () { $this->redis->close(); @@ -467,9 +504,12 @@ public function testEmitsNoCloseEventButWillCancelIdleTimerWhenUnderlyingConnect $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); + $loop = $this->createMock(LoopInterface::class); $timer = $this->createMock(TimerInterface::class); - $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); - $this->loop->expects($this->once())->method('cancelTimer')->with($timer); + $loop->expects($this->once())->method('addTimer')->willReturn($timer); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + assert($loop instanceof LoopInterface); + Loop::set($loop); $this->redis->on('close', $this->expectCallableNever()); @@ -558,7 +598,10 @@ public function testSubscribeWillResolveWhenUnderlyingClientResolvesSubscribeAnd $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->never())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->subscribe('foo'); $this->assertTrue(is_callable($subscribeHandler)); @@ -587,7 +630,10 @@ public function testUnsubscribeAfterSubscribeWillResolveWhenUnderlyingClientReso $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $this->loop->expects($this->once())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->subscribe('foo'); $this->assertTrue(is_callable($subscribeHandler)); @@ -617,7 +663,10 @@ public function testBlpopWillRejectWhenUnderlyingClientClosesWhileWaitingForResp $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $this->loop->expects($this->never())->method('addTimer'); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->never())->method('addTimer'); + assert($loop instanceof LoopInterface); + Loop::set($loop); $promise = $this->redis->blpop('list');