From 70886b2326a786013763e279cf07fda90fd75ebc Mon Sep 17 00:00:00 2001 From: Eugene Kirdzei Date: Mon, 30 Oct 2017 12:16:32 +0200 Subject: [PATCH] Make more tests (#5) --- composer.json | 5 ++ readme.md | 4 +- src/Console/ListenCommand.php | 4 +- src/Dispatcher.php | 13 ++++- src/MessageProcessor.php | 24 ++++----- tests/BroadcastFactoryTest.php | 32 ++++++++++++ tests/ConsumerFactoryTest.php | 36 ++++++++++++++ tests/DispatcherTest.php | 89 ++++++++++++++++++++++++++++++++++ tests/JobTest.php | 17 +++---- tests/MessageFactoryTest.php | 29 +++++++++++ tests/MessageProcessorTest.php | 15 +++--- tests/TestCase.php | 11 +++++ 12 files changed, 242 insertions(+), 37 deletions(-) create mode 100644 tests/BroadcastFactoryTest.php create mode 100644 tests/ConsumerFactoryTest.php create mode 100644 tests/DispatcherTest.php create mode 100644 tests/MessageFactoryTest.php create mode 100644 tests/TestCase.php diff --git a/composer.json b/composer.json index 1e35466..6c24ce9 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,11 @@ "src/helpers.php" ] }, + "autoload-dev": { + "psr-4": { + "Nuwber\\Events\\Tests\\": "tests/" + } + }, "extra": { "laravel": { "providers": [ diff --git a/readme.md b/readme.md index 31ab9b0..7b152bb 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ Nuwber's broadcasting events provides a simple observer implementation, allowing Do not confuse this package with Laravel's broadcast. This package was made to communicate in backend-backend way. -Generally, this is compilation of LAravel's [events](https://laravel.com/docs/events) and [queues](https://laravel.com/docs/queues). +Generally, this is compilation of Laravel's [events](https://laravel.com/docs/events) and [queues](https://laravel.com/docs/queues). Listener classes are typically stored in the `app/Listeners` folder. You may use Laravel's artisan command to generate them as it described in the [official documentation](https://laravel.com/docs/events). @@ -136,7 +136,7 @@ After this command start all registered in project events will be registered in Currently it doesn't detaches command from console, so you can just add `&` at the end of command: ``` -php artian events:listen > /dev/null & +php artisan events:listen > /dev/null & ``` In this case you need to remember that you have organize some system such as [Supervisor](http://supervisord.org/) or [pm2](http://pm2.keymetrics.io/) which will controll your processes. diff --git a/src/Console/ListenCommand.php b/src/Console/ListenCommand.php index ac4c780..55295db 100644 --- a/src/Console/ListenCommand.php +++ b/src/Console/ListenCommand.php @@ -225,7 +225,7 @@ protected function listenForSignals() * @param int $memoryLimit * @return bool */ - public function memoryExceeded($memoryLimit) + protected function memoryExceeded($memoryLimit) { return (memory_get_usage(true) / 1024 / 1024) >= $memoryLimit; } @@ -236,7 +236,7 @@ public function memoryExceeded($memoryLimit) * @param int $status * @return void */ - public function stop($status = 0) + protected function stop($status = 0) { exit($status); } diff --git a/src/Dispatcher.php b/src/Dispatcher.php index 6f0050b..4cfa5bc 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -25,7 +25,7 @@ public function listen($events, $listener) if (Str::contains($event, '*')) { $this->setupWildcardListen($event, $listener); } else { - $this->listeners[$event][$listener] = $this->makeListener($listener); + $this->listeners[$event][$this->getListenerClass($listener)][] = $this->makeListener($listener); } } } @@ -39,6 +39,15 @@ public function listen($events, $listener) */ protected function setupWildcardListen($event, $listener) { - $this->wildcards[$event][$listener] = $this->makeListener($listener, true); + $this->wildcards[$event][$this->getListenerClass($listener)][] = $this->makeListener($listener, true); + } + + protected function getListenerClass($listener) + { + if ($listener instanceof \Closure) { + return \Closure::class; + } + + return $listener; } } diff --git a/src/MessageProcessor.php b/src/MessageProcessor.php index 0075ddf..e0ddff1 100644 --- a/src/MessageProcessor.php +++ b/src/MessageProcessor.php @@ -98,17 +98,19 @@ protected function makeJobs(PsrConsumer $consumer, PsrMessage $payload) { $event = $payload->getRoutingKey(); - foreach ($this->broadcastEvents->getListeners($event) as $name => $listener) { - yield new Job( - $this->container, - $this->context, - $consumer, - $payload, - $this->connectionName, - $event, - $name, - $listener - ); + foreach ($this->broadcastEvents->getListeners($event) as $name => $listeners) { + foreach ($listeners as $listener) { + yield new Job( + $this->container, + $this->context, + $consumer, + $payload, + $this->connectionName, + $event, + $name, + $listener + ); + } } } diff --git a/tests/BroadcastFactoryTest.php b/tests/BroadcastFactoryTest.php new file mode 100644 index 0000000..af8d7fc --- /dev/null +++ b/tests/BroadcastFactoryTest.php @@ -0,0 +1,32 @@ +shouldReceive('send') + ->with($topic, $message) + ->once(); + + $context = \Mockery::mock(AmqpContext::class)->makePartial(); + $context->shouldReceive('createProducer') + ->andReturn($producer); + + $factory = new BroadcastFactory($context, $topic); + + self::assertNull($factory->send($message)); + } +} diff --git a/tests/ConsumerFactoryTest.php b/tests/ConsumerFactoryTest.php new file mode 100644 index 0000000..3708024 --- /dev/null +++ b/tests/ConsumerFactoryTest.php @@ -0,0 +1,36 @@ +makePartial(); + + $context = \Mockery::mock(AmqpContext::class)->makePartial(); + $context->shouldReceive('createConsumer') + ->once() + ->andReturn($consumer); + + $context->shouldReceive('createTemporaryQueue') + ->once() + ->andReturn($queue); + + $events = ['item.created', 'item.updated']; + $context->shouldReceive('bind')->twice(); + + $factory = new ConsumerFactory($context, new AmqpTopic('events')); + + self::assertEquals($consumer, $factory->make($events)); + } +} diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php new file mode 100644 index 0000000..2454ecc --- /dev/null +++ b/tests/DispatcherTest.php @@ -0,0 +1,89 @@ + [ + 'Listeners/Class1', + 'Listeners/Class2', + ], + 'item.updated' => [ + 'Listeners/Class3' + ], + 'item.*' => [ + 'Listeners/Class4' + ] + ]; + + public function testGetEvents() + { + $events = array_keys($this->listen); + + self::assertEquals($events, $this->setupDispatcher()->getEvents()); + } + + public function testListen() + { + $dispatcher = new Dispatcher(); + $dispatcher->listen('item.event', function() {}); + + self::assertTrue($dispatcher->hasListeners('item.event')); + } + + public function testAddedClosureListeners() + { + $dispatcher = new Dispatcher(); + + $dispatcher->listen('item.event', function() {}); + $dispatcher->listen('item.event', function() {}); + + $listeners = $dispatcher->getListeners('item.event'); + + self::assertCount(1, $listeners); + + self::assertEquals(['Closure'], array_keys($listeners)); + + self::assertCount(2, $listeners['Closure']); + } + + public function testCorrectWildcardHandling() + { + $listeners = $this->setupDispatcher() + ->getListeners('item.event'); + + self::assertCount(1, $listeners); + + + self::assertEquals(['Listeners/Class4'], array_keys($listeners)); + } + + public function testListenersAddedWithNameAsKey() + { + $listeners = $this->setupDispatcher() + ->getListeners('item.created'); + + // Expected 3 because 'item.created' + 'item.*' + self::assertCount(3, $listeners); + + self::assertEquals(['Listeners/Class1', 'Listeners/Class2', 'Listeners/Class4'], array_keys($listeners)); + } + + private function setupDispatcher() + { + $dispatcher = new Dispatcher(); + + foreach ($this->listen as $event => $listeners) { + foreach ($listeners as $listener) { + $dispatcher->listen($event, $listener); + } + } + + return $dispatcher; + } +} diff --git a/tests/JobTest.php b/tests/JobTest.php index 2d95031..07465a5 100644 --- a/tests/JobTest.php +++ b/tests/JobTest.php @@ -1,14 +1,13 @@ shouldReceive('getBody')->andReturn('{"id": 1}'); + $message->shouldReceive('getBody') + ->andReturn('{"id": 1}'); $this->job = new Job( m::mock(Container::class), @@ -38,21 +38,16 @@ public function setUp() ); } - public function tearDown() - { - m::close(); - } - public function testFire() { - Assert::assertEquals("Event: $this->event. Item id: 1", $this->job->fire()); + self::assertEquals("Event: $this->event. Item id: 1", $this->job->fire()); } public function testGetName() { $expectedMessage = "$this->connectionName: $this->event:$this->listenerClass"; - Assert::assertEquals($expectedMessage, $this->job->getName()); + self::assertEquals($expectedMessage, $this->job->getName()); } } diff --git a/tests/MessageFactoryTest.php b/tests/MessageFactoryTest.php new file mode 100644 index 0000000..db0fa63 --- /dev/null +++ b/tests/MessageFactoryTest.php @@ -0,0 +1,29 @@ + 1]; + $event = 'item.created'; + + $expectedMessage = new AmqpMessage(json_encode($data)); + $expectedMessage->setRoutingKey($event); + + $context = \Mockery::mock(AmqpContext::class)->makePartial(); + + $factory = new MessageFactory($context, new AmqpTopic('events')); + + $message = $factory->make($event, $data); + + self::assertEquals($expectedMessage, $message); + } +} diff --git a/tests/MessageProcessorTest.php b/tests/MessageProcessorTest.php index a566f67..0684f4c 100644 --- a/tests/MessageProcessorTest.php +++ b/tests/MessageProcessorTest.php @@ -1,6 +1,6 @@ listeners = [ - 'ListenerClass' => function () { + 'ListenerClass' => [function () { throw new FailedException(); - } + }] ]; $broadcastEvents = m::spy(Dispatcher::class)->makePartial(); @@ -120,9 +122,4 @@ private function createConsumer() return new AmqpConsumer($channel, $queue, new Buffer(), 'basic_get'); } - - public function tearDown() - { - m::close(); - } } diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..234dcef --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,11 @@ +