From fc1d028b6a625a4797739139e2fbd70bc19828c5 Mon Sep 17 00:00:00 2001
From: Marco Stoll <marco.stoll@rocketmail.com>
Date: Fri, 21 Jun 2019 10:36:57 +0200
Subject: [PATCH] [REFACTOR] reorganize namespaces for factories

---
 .../Factories/EventsFactory.php               |   5 +-
 src/{Services => }/Factories/SF.php           |   2 +-
 .../Factories/ServicesFactory.php             |   5 +-
 src/Services/{ => Events}/EventBroker.php     |   5 +-
 src/Services/Traits/EventEmitterTrait.php     |   6 +-
 src/Services/Traits/ServiceLocatorTrait.php   |   2 +-
 .../Factories/EventsFactoryTest.php           |   4 +-
 tests/{Services => }/Factories/SFTest.php     |   6 +-
 .../Factories/ServicesFactoryTest.php         |   4 +-
 tests/Services/EventBrokerTest.php            | 287 -----------------
 tests/Services/Events/EventBrokerTest.php     | 288 ++++++++++++++++++
 11 files changed, 307 insertions(+), 307 deletions(-)
 rename src/{Services => }/Factories/EventsFactory.php (94%)
 rename src/{Services => }/Factories/SF.php (93%)
 rename src/{Services => }/Factories/ServicesFactory.php (97%)
 rename src/Services/{ => Events}/EventBroker.php (98%)
 rename tests/{Services => }/Factories/EventsFactoryTest.php (91%)
 rename tests/{Services => }/Factories/SFTest.php (86%)
 rename tests/{Services => }/Factories/ServicesFactoryTest.php (97%)
 delete mode 100644 tests/Services/EventBrokerTest.php
 create mode 100644 tests/Services/Events/EventBrokerTest.php

diff --git a/src/Services/Factories/EventsFactory.php b/src/Factories/EventsFactory.php
similarity index 94%
rename from src/Services/Factories/EventsFactory.php
rename to src/Factories/EventsFactory.php
index 6f76a06..f398f8a 100644
--- a/src/Services/Factories/EventsFactory.php
+++ b/src/Factories/EventsFactory.php
@@ -8,17 +8,16 @@
  */
 declare(strict_types=1);
 
-namespace FF\Services\Factories;
+namespace FF\Factories;
 
 use FF\Events\AbstractEvent;
-use FF\Factories\AbstractFactory;
 use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
 use FF\Factories\ClassLocators\ClassLocatorInterface;
 
 /**
  * Class EventsFactory
  *
- * @package FF\Services\Factories
+ * @package FF\Factories
  */
 class EventsFactory extends AbstractFactory
 {
diff --git a/src/Services/Factories/SF.php b/src/Factories/SF.php
similarity index 93%
rename from src/Services/Factories/SF.php
rename to src/Factories/SF.php
index 51762dc..122d9e1 100644
--- a/src/Services/Factories/SF.php
+++ b/src/Factories/SF.php
@@ -8,7 +8,7 @@
  */
 declare(strict_types=1);
 
-namespace FF\Services\Factories;
+namespace FF\Factories;
 
 /**
  * Class SF
diff --git a/src/Services/Factories/ServicesFactory.php b/src/Factories/ServicesFactory.php
similarity index 97%
rename from src/Services/Factories/ServicesFactory.php
rename to src/Factories/ServicesFactory.php
index b528cc0..6f9dab0 100644
--- a/src/Services/Factories/ServicesFactory.php
+++ b/src/Factories/ServicesFactory.php
@@ -8,9 +8,8 @@
  */
 declare(strict_types=1);
 
-namespace FF\Services\Factories;
+namespace FF\Factories;
 
-use FF\Factories\AbstractSingletonFactory;
 use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
 use FF\Factories\ClassLocators\ClassLocatorInterface;
 use FF\Factories\Exceptions\ClassNotFoundException;
@@ -20,7 +19,7 @@ use FF\Services\Exceptions\ConfigurationException;
 /**
  * Class ServicesFactory
  *
- * @package FF\Services\Factories
+ * @package FF\Factories
  */
 class ServicesFactory extends AbstractSingletonFactory
 {
diff --git a/src/Services/EventBroker.php b/src/Services/Events/EventBroker.php
similarity index 98%
rename from src/Services/EventBroker.php
rename to src/Services/Events/EventBroker.php
index aa9232a..26d99ac 100644
--- a/src/Services/EventBroker.php
+++ b/src/Services/Events/EventBroker.php
@@ -8,13 +8,14 @@
  */
 declare(strict_types=1);
 
-namespace FF\Services;
+namespace FF\Services\Events;
 
 use FF\DataStructures\IndexedCollection;
 use FF\DataStructures\OrderedCollection;
 use FF\Events\AbstractEvent;
+use FF\Factories\EventsFactory;
 use FF\Factories\Exceptions\ClassNotFoundException;
-use FF\Services\Factories\EventsFactory;
+use FF\Services\AbstractService;
 
 /**
  * Class EventBroker
diff --git a/src/Services/Traits/EventEmitterTrait.php b/src/Services/Traits/EventEmitterTrait.php
index d004f2b..2b8da54 100644
--- a/src/Services/Traits/EventEmitterTrait.php
+++ b/src/Services/Traits/EventEmitterTrait.php
@@ -10,8 +10,8 @@ declare(strict_types=1);
 
 namespace FF\Services\Traits;
 
-use FF\Services\EventBroker;
-use FF\Services\Factories\SF;
+use FF\Factories\SF;
+use FF\Services\Events\EventBroker;
 
 /**
  * Trait EventEmitterTrait
@@ -35,7 +35,7 @@ trait EventEmitterTrait
         static $eventBroker = null;
 
         if (is_null($eventBroker)) {
-            $eventBroker = SF::i()->get('EventBroker');
+            $eventBroker = SF::i()->get('Events\EventBroker');
         }
 
         $eventBroker->fire($classIdentifier, ...$args);
diff --git a/src/Services/Traits/ServiceLocatorTrait.php b/src/Services/Traits/ServiceLocatorTrait.php
index 4dde715..f29e33d 100644
--- a/src/Services/Traits/ServiceLocatorTrait.php
+++ b/src/Services/Traits/ServiceLocatorTrait.php
@@ -10,8 +10,8 @@ declare(strict_types=1);
 
 namespace FF\Services\Traits;
 
+use FF\Factories\SF;
 use FF\Services\AbstractService;
-use FF\Services\Factories\SF;
 
 /**
  * Trait ServiceLocatorTrait
diff --git a/tests/Services/Factories/EventsFactoryTest.php b/tests/Factories/EventsFactoryTest.php
similarity index 91%
rename from tests/Services/Factories/EventsFactoryTest.php
rename to tests/Factories/EventsFactoryTest.php
index 2b8aad7..930b1f2 100644
--- a/tests/Services/Factories/EventsFactoryTest.php
+++ b/tests/Factories/EventsFactoryTest.php
@@ -8,10 +8,10 @@
  */
 declare(strict_types=1);
 
-namespace FF\Tests\Services\Factories;
+namespace FF\Tests\Factories;
 
 use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
-use FF\Services\Factories\EventsFactory;
+use FF\Factories\EventsFactory;
 use PHPUnit\Framework\TestCase;
 
 /**
diff --git a/tests/Services/Factories/SFTest.php b/tests/Factories/SFTest.php
similarity index 86%
rename from tests/Services/Factories/SFTest.php
rename to tests/Factories/SFTest.php
index 399d424..685049a 100644
--- a/tests/Services/Factories/SFTest.php
+++ b/tests/Factories/SFTest.php
@@ -8,10 +8,10 @@
  */
 declare(strict_types=1);
 
-namespace FF\Tests\Services;
+namespace FF\Tests\Factories;
 
-use FF\Services\Factories\ServicesFactory;
-use FF\Services\Factories\SF;
+use FF\Factories\ServicesFactory;
+use FF\Factories\SF;
 use PHPUnit\Framework\TestCase;
 
 /**
diff --git a/tests/Services/Factories/ServicesFactoryTest.php b/tests/Factories/ServicesFactoryTest.php
similarity index 97%
rename from tests/Services/Factories/ServicesFactoryTest.php
rename to tests/Factories/ServicesFactoryTest.php
index 3dce62b..12e3cde 100644
--- a/tests/Services/Factories/ServicesFactoryTest.php
+++ b/tests/Factories/ServicesFactoryTest.php
@@ -8,12 +8,12 @@
  */
 declare(strict_types=1);
 
-namespace FF\Tests\Services\Factories {
+namespace FF\Tests\Factories {
 
     use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
     use FF\Factories\Exceptions\ClassNotFoundException;
+    use FF\Factories\ServicesFactory;
     use FF\Services\Exceptions\ConfigurationException;
-    use FF\Services\Factories\ServicesFactory;
     use FF\Tests\Services\ServiceOne;
     use FF\Tests\Services\ServiceTwo;
     use PHPUnit\Framework\TestCase;
diff --git a/tests/Services/EventBrokerTest.php b/tests/Services/EventBrokerTest.php
deleted file mode 100644
index f06f527..0000000
--- a/tests/Services/EventBrokerTest.php
+++ /dev/null
@@ -1,287 +0,0 @@
-<?php
-/**
- * Definition of EventBrokerTest
- *
- * @author Marco Stoll <marco@fast-forward-encoding.de>
- * @copyright 2019-forever Marco Stoll
- * @filesource
- */
-declare(strict_types=1);
-
-namespace FF\Tests\Services {
-
-    use FF\DataStructures\IndexedCollection;
-    use FF\DataStructures\OrderedCollection;
-    use FF\Services\EventBroker;
-    use FF\Services\Factories\EventsFactory;
-    use FF\Tests\Services\Events\EventA;
-    use FF\Tests\Services\Events\EventB;
-    use PHPUnit\Framework\TestCase;
-
-    /**
-     * Test EventBrokerTest
-     *
-     * @package FF\Tests
-     */
-    class EventBrokerTest extends TestCase
-    {
-        /**
-         * @var EventBroker
-         */
-        protected $uut;
-
-        /**
-         * {@inheritdoc}
-         */
-        protected function setUp(): void
-        {
-            $this->uut = new EventBroker();
-            $this->uut->getEventsFactory()
-                ->getClassLocator()
-                ->prependNamespaces(__NAMESPACE__);
-        }
-
-        /**
-         * {@inheritdoc}
-         */
-        protected function tearDown(): void
-        {
-            $this->uut->unsubscribeAll('EventA');
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testGetEventsFactory()
-        {
-            $this->assertInstanceOf(EventsFactory::class, $this->uut->getEventsFactory());
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testGetSubscriptions()
-        {
-            $this->assertInstanceOf(IndexedCollection::class, $this->uut->getSubscriptions());
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testGetSubscribers()
-        {
-            $this->assertInstanceOf(OrderedCollection::class, $this->uut->getSubscribers('EventA'));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testSubscribe()
-        {
-            $callback = [new ListenerA(), 'shoutA'];
-
-            $same = $this->uut->subscribe($callback, 'EventA');
-            $this->assertSame($this->uut, $same);
-            $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
-            $this->assertSame($callback, $this->uut->getSubscribers('EventA')->getFirst());
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testSubscribeRepeated()
-        {
-            $callback = [new ListenerA(), 'shoutA'];
-
-            $this->uut->subscribe($callback, 'EventA')->subscribe($callback, 'EventA');
-            $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testSubscribeAppend()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-            $callback2 = [new ListenerA(), 'shoutA'];
-
-            $this->uut->subscribe($callback1, 'EventA')
-                ->subscribe($callback2, 'EventA');
-            $this->assertSame($callback1, $this->uut->getSubscribers('EventA')->get(0));
-            $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(1));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testSubscribeFirst()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-            $callback2 = [new ListenerA(), 'shoutA'];
-
-            $same = $this->uut->subscribe($callback1, 'EventA')
-                ->subscribeFirst($callback2, 'EventA');
-            $this->assertSame($this->uut, $same);
-            $this->assertSame($callback1, $this->uut->getSubscribers('EventA')->get(1));
-            $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(0));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testUnsubscribe()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-
-            $this->uut->subscribe($callback1, 'EventA')
-                ->subscribe($callback1, 'EventB')
-                ->unsubscribe($callback1);
-            $this->assertTrue($this->uut->getSubscribers('EventA')->isEmpty());
-            $this->assertTrue($this->uut->getSubscribers('EventB')->isEmpty());
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testUnsubscribeNamed()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-            $callback2 = [new ListenerA(), 'shoutA'];
-
-            $same = $this->uut->subscribe($callback1, 'EventA')
-                ->subscribe($callback2, 'EventA')
-                ->unsubscribe($callback1, 'EventA');
-            $this->assertSame($this->uut, $same);
-            $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
-            $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(0));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testUnsubscribeAll()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-            $callback2 = [new ListenerA(), 'shoutA'];
-
-            $same = $this->uut->subscribe($callback1, 'EventA')
-                ->subscribe($callback2, 'EventA')
-                ->unsubscribeAll('EventA');
-            $this->assertSame($this->uut, $same);
-            $this->assertTrue($this->uut->getSubscribers('EventA')->isEmpty());
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testHasSubscribers()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-
-            $this->uut->subscribe($callback1, 'EventA');
-
-            $this->assertTrue($this->uut->hasSubscribers('EventA'));
-            $this->assertFalse($this->uut->hasSubscribers('EventB'));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testIsSubscribed()
-        {
-            $callback1 = [new ListenerA(), 'shoutA'];
-            $callback2 = [new ListenerA(), 'shoutB'];
-
-            $this->uut->subscribe($callback1, 'EventA');
-
-            $this->assertTrue($this->uut->isSubscribed($callback1, 'EventA'));
-            $this->assertFalse($this->uut->isSubscribed($callback1, 'EventB'));
-            $this->assertFalse($this->uut->isSubscribed($callback2, 'EventA'));
-            $this->assertFalse($this->uut->isSubscribed($callback2, 'EventB'));
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testFire()
-        {
-            $same = $this->uut->fire('EventA', 'foo');
-            $this->assertSame($this->uut, $same);
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testFireWithListener()
-        {
-            $this->expectOutputString('foo');
-
-            $this->uut->subscribe([new ListenerA(), 'shoutA'], 'EventA')
-                ->fire('EventA', 'foo');
-        }
-
-        /**
-         * Tests the namesake method/feature
-         */
-        public function testFireCancel()
-        {
-            $this->expectOutputString('foo'); // output would be 'foofoo' if event canceling does not work
-
-            $this->uut->subscribe([new ListenerA(), 'cancelA'], 'EventA')
-                ->subscribe([new ListenerB(), 'neverToReach'], 'EventA')
-                ->fire('EventA', 'foo');
-        }
-    }
-
-    class ListenerA
-    {
-        public function shoutA(EventA $event)
-        {
-            print $event->content;
-        }
-
-        public function shoutB(EventB $event)
-        {
-            print $event->content;
-        }
-
-        public function cancelA(EventA $event)
-        {
-            print $event->content;
-            $event->cancel();
-        }
-    }
-
-    class ListenerB extends ListenerA
-    {
-        public function shoutB(EventB $event)
-        {
-            print $event->content;
-        }
-
-        public function neverToReach(EventA $event)
-        {
-            print $event->content;
-        }
-    }
-}
-
-namespace FF\Tests\Services\Events {
-
-    use FF\Events\AbstractEvent;
-
-    class EventA extends AbstractEvent
-    {
-        public $content;
-
-        public function __construct(string $content)
-        {
-            $this->content = $content;
-        }
-    }
-
-    class EventB extends EventA
-    {
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Services/Events/EventBrokerTest.php b/tests/Services/Events/EventBrokerTest.php
new file mode 100644
index 0000000..9ab656e
--- /dev/null
+++ b/tests/Services/Events/EventBrokerTest.php
@@ -0,0 +1,288 @@
+<?php
+/**
+ * Definition of EventBrokerTest
+ *
+ * @author Marco Stoll <marco@fast-forward-encoding.de>
+ * @copyright 2019-forever Marco Stoll
+ * @filesource
+ */
+declare(strict_types=1);
+
+namespace FF\Tests\Services\Events;
+
+use FF\DataStructures\IndexedCollection;
+use FF\DataStructures\OrderedCollection;
+use FF\Events\AbstractEvent;
+use FF\Factories\EventsFactory;
+use FF\Services\Events\EventBroker;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Test EventBrokerTest
+ *
+ * @package FF\Tests
+ */
+class EventBrokerTest extends TestCase
+{
+    /**
+     * @var EventBroker
+     */
+    protected $uut;
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function setUp(): void
+    {
+        $this->uut = new EventBroker();
+        $this->uut->getEventsFactory()
+            ->getClassLocator()
+            ->prependNamespaces('FF\Tests\Services');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function tearDown(): void
+    {
+        $this->uut->unsubscribeAll('EventA');
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testGetEventsFactory()
+    {
+        $this->assertInstanceOf(EventsFactory::class, $this->uut->getEventsFactory());
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testGetSubscriptions()
+    {
+        $this->assertInstanceOf(IndexedCollection::class, $this->uut->getSubscriptions());
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testGetSubscribers()
+    {
+        $this->assertInstanceOf(OrderedCollection::class, $this->uut->getSubscribers('EventA'));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testSubscribe()
+    {
+        $callback = [new ListenerA(), 'shoutA'];
+
+        $same = $this->uut->subscribe($callback, 'EventA');
+        $this->assertSame($this->uut, $same);
+        $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
+        $this->assertSame($callback, $this->uut->getSubscribers('EventA')->getFirst());
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testSubscribeRepeated()
+    {
+        $callback = [new ListenerA(), 'shoutA'];
+
+        $this->uut->subscribe($callback, 'EventA')->subscribe($callback, 'EventA');
+        $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testSubscribeAppend()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+        $callback2 = [new ListenerA(), 'shoutA'];
+
+        $this->uut->subscribe($callback1, 'EventA')
+            ->subscribe($callback2, 'EventA');
+        $this->assertSame($callback1, $this->uut->getSubscribers('EventA')->get(0));
+        $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(1));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testSubscribeFirst()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+        $callback2 = [new ListenerA(), 'shoutA'];
+
+        $same = $this->uut->subscribe($callback1, 'EventA')
+            ->subscribeFirst($callback2, 'EventA');
+        $this->assertSame($this->uut, $same);
+        $this->assertSame($callback1, $this->uut->getSubscribers('EventA')->get(1));
+        $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(0));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testUnsubscribe()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+
+        $this->uut->subscribe($callback1, 'EventA')
+            ->subscribe($callback1, 'EventB')
+            ->unsubscribe($callback1);
+        $this->assertTrue($this->uut->getSubscribers('EventA')->isEmpty());
+        $this->assertTrue($this->uut->getSubscribers('EventB')->isEmpty());
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testUnsubscribeNamed()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+        $callback2 = [new ListenerA(), 'shoutA'];
+
+        $same = $this->uut->subscribe($callback1, 'EventA')
+            ->subscribe($callback2, 'EventA')
+            ->unsubscribe($callback1, 'EventA');
+        $this->assertSame($this->uut, $same);
+        $this->assertEquals(1, count($this->uut->getSubscribers('EventA')));
+        $this->assertSame($callback2, $this->uut->getSubscribers('EventA')->get(0));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testUnsubscribeAll()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+        $callback2 = [new ListenerA(), 'shoutA'];
+
+        $same = $this->uut->subscribe($callback1, 'EventA')
+            ->subscribe($callback2, 'EventA')
+            ->unsubscribeAll('EventA');
+        $this->assertSame($this->uut, $same);
+        $this->assertTrue($this->uut->getSubscribers('EventA')->isEmpty());
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testHasSubscribers()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+
+        $this->uut->subscribe($callback1, 'EventA');
+
+        $this->assertTrue($this->uut->hasSubscribers('EventA'));
+        $this->assertFalse($this->uut->hasSubscribers('EventB'));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testIsSubscribed()
+    {
+        $callback1 = [new ListenerA(), 'shoutA'];
+        $callback2 = [new ListenerA(), 'shoutB'];
+
+        $this->uut->subscribe($callback1, 'EventA');
+
+        $this->assertTrue($this->uut->isSubscribed($callback1, 'EventA'));
+        $this->assertFalse($this->uut->isSubscribed($callback1, 'EventB'));
+        $this->assertFalse($this->uut->isSubscribed($callback2, 'EventA'));
+        $this->assertFalse($this->uut->isSubscribed($callback2, 'EventB'));
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testFire()
+    {
+        $same = $this->uut->fire('EventA', 'foo');
+        $this->assertSame($this->uut, $same);
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testFireWithListener()
+    {
+        $this->expectOutputString('foo');
+
+        $this->uut->subscribe([new ListenerA(), 'shoutA'], 'EventA')
+            ->fire('EventA', 'foo');
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testFireCancel()
+    {
+        $this->expectOutputString('foo'); // output would be 'foofoo' if event canceling does not work
+
+        $this->uut->subscribe([new ListenerA(), 'cancelA'], 'EventA')
+            ->subscribe([new ListenerB(), 'neverToReach'], 'EventA')
+            ->fire('EventA', 'foo');
+    }
+
+    /**
+     * Tests the namesake method/feature
+     */
+    public function testGetClassIdentifier()
+    {
+        $this->assertEquals('Events\EventBroker', EventBroker::getClassIdentifier());
+    }
+}
+
+class ListenerA
+{
+    public function shoutA(EventA $event)
+    {
+        print $event->content;
+    }
+
+    public function shoutB(EventB $event)
+    {
+        print $event->content;
+    }
+
+    public function cancelA(EventA $event)
+    {
+        print $event->content;
+        $event->cancel();
+    }
+}
+
+class ListenerB extends ListenerA
+{
+    public function shoutB(EventB $event)
+    {
+        print $event->content;
+    }
+
+    public function neverToReach(EventA $event)
+    {
+        print $event->content;
+    }
+}
+
+class EventA extends AbstractEvent
+{
+    public $content;
+
+    public function __construct(string $content)
+    {
+        $this->content = $content;
+    }
+}
+
+class EventB extends EventA
+{
+
+}
\ No newline at end of file