diff --git a/payment.services.yml b/payment.services.yml
index 6e252fe..c885de5 100644
--- a/payment.services.yml
+++ b/payment.services.yml
@@ -1,7 +1,12 @@
 services:
   payment.event_dispatcher:
-    class: Drupal\payment\EventDispatcher
+    class: Drupal\payment\EventDispatcherCollection
+    tags:
+      - { name: service_collector, tag: payment.event_dispatcher, call: addEventDispatcher }
+  payment.event_dispatcher.symfony:
+    class: Drupal\payment\SymfonyEventDispatcher
     arguments: ['@event_dispatcher']
+      - { name: payment.event_dispatcher }
   payment.logger:
     parent: logger.channel_base
     arguments: ['payment']
diff --git a/src/EventDispatcher.php b/src/EventDispatcher.php
deleted file mode 100644
index 539dbad..0000000
--- a/src/EventDispatcher.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\payment\EventDispatcher.
- */
-
-namespace Drupal\payment;
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\payment\Entity\PaymentInterface;
-use Drupal\payment\Event\PaymentEvents;
-use Drupal\payment\Event\PaymentExecuteAccess;
-use Drupal\payment\Event\PaymentPreCapture;
-use Drupal\payment\Event\PaymentPreExecute;
-use Drupal\payment\Event\PaymentPreRefund;
-use Drupal\payment\Event\PaymentQueuePaymentIdsAlter;
-use Drupal\payment\Event\PaymentStatusSet;
-use Drupal\payment\Event\PaymentTypePreResumeContext;
-use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
-use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface as SymfonyEventDispatcherInterface;
-
-/**
- * Provides a Payment event dispatcher.
- */
-class EventDispatcher implements EventDispatcherInterface {
-
-  /**
-   * The Symfony event dispatcher.
-   *
-   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
-   */
-  protected $symfonyEventDispatcher;
-
-  /**
-   * Constructs a new instance.
-   *
-   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $symfony_event_dispatcher
-   */
-  public function __construct(SymfonyEventDispatcherInterface $symfony_event_dispatcher) {
-    $this->symfonyEventDispatcher = $symfony_event_dispatcher;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, array $payment_ids) {
-    $event = new PaymentQueuePaymentIdsAlter($queue_id, $category_id, $owner_id, $payment_ids);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_QUEUE_PAYMENT_IDS_ALTER, $event);
-    $payment_ids = $event->getPaymentIds();
-
-    return $payment_ids;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setPaymentStatus(PaymentInterface $payment, PaymentStatusInterface $previous_payment_status = NULL) {
-    $event = new PaymentStatusSet($payment, $previous_payment_status);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_STATUS_SET, $event);
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   */
-  public function preExecutePayment(PaymentInterface $payment) {
-    $event = new PaymentPreExecute($payment);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_EXECUTE, $event);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function executePaymentAccess(PaymentInterface $payment, PaymentMethodInterface $payment_method, AccountInterface $account) {
-    $event = new PaymentExecuteAccess($payment, $payment_method, $account);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_EXECUTE_ACCESS, $event);
-
-    return $event->getAccessResult();
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   */
-  public function preCapturePayment(PaymentInterface $payment) {
-    $event = new PaymentPreCapture($payment);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_CAPTURE, $event);
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   */
-  public function preRefundPayment(PaymentInterface $payment) {
-    $event = new PaymentPreRefund($payment);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_REFUND, $event);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function preResumeContext(PaymentInterface $payment) {
-    $event = new PaymentTypePreResumeContext($payment);
-    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_TYPE_PRE_RESUME_CONTEXT, $event);
-  }
-
-}
diff --git a/src/EventDispatcherCollection.php b/src/EventDispatcherCollection.php
new file mode 100644
index 0000000..905d3bc
--- /dev/null
+++ b/src/EventDispatcherCollection.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\EventDispatcherCollection.
+ */
+
+namespace Drupal\payment;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\payment\Entity\PaymentInterface;
+use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
+use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
+
+/**
+ * Dispatches events to a collection of event dispatchers.
+ */
+class EventDispatcherCollection implements EventDispatcherInterface {
+
+  /**
+   * The event dispatchers.
+   *
+   * @var \Drupal\payment\EventDispatcherInterface[]
+   */
+  protected $eventDispatchers = [];
+
+  /**
+   * Adds an event dispatcher to the collection.
+   *
+   * @param \Drupal\payment\EventDispatcherInterface $event_dispatcher
+   *
+   * @return $this
+   */
+  public function addEventDispatcher(EventDispatcherInterface $event_dispatcher) {
+    $this->eventDispatchers[] = $event_dispatcher;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, array $payment_ids) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $payment_ids = $event_dispatcher->alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, $payment_ids);
+    }
+
+    return $payment_ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPaymentStatus(PaymentInterface $payment, PaymentStatusInterface $previous_payment_status = NULL) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $event_dispatcher->setPaymentStatus($payment, $previous_payment_status);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preExecutePayment(PaymentInterface $payment) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $event_dispatcher->preExecutePayment($payment);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function executePaymentAccess(PaymentInterface $payment, PaymentMethodInterface $payment_method, AccountInterface $account) {
+    $access = AccessResult::neutral();
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $access = $access->orIf($event_dispatcher->executePaymentAccess($payment, $payment_method, $account));
+    }
+
+    return $access;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preCapturePayment(PaymentInterface $payment) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $event_dispatcher->preCapturePayment($payment);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preRefundPayment(PaymentInterface $payment) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $event_dispatcher->preRefundPayment($payment);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preResumeContext(PaymentInterface $payment) {
+    foreach ($this->eventDispatchers as $event_dispatcher) {
+      $event_dispatcher->preResumeContext($payment);
+    }
+  }
+
+}
diff --git a/src/SymfonyEventDispatcher.php b/src/SymfonyEventDispatcher.php
new file mode 100644
index 0000000..2a9c8d9
--- /dev/null
+++ b/src/SymfonyEventDispatcher.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\SymfonyEventDispatcher.
+ */
+
+namespace Drupal\payment;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\payment\Entity\PaymentInterface;
+use Drupal\payment\Event\PaymentEvents;
+use Drupal\payment\Event\PaymentExecuteAccess;
+use Drupal\payment\Event\PaymentPreCapture;
+use Drupal\payment\Event\PaymentPreExecute;
+use Drupal\payment\Event\PaymentPreRefund;
+use Drupal\payment\Event\PaymentQueuePaymentIdsAlter;
+use Drupal\payment\Event\PaymentStatusSet;
+use Drupal\payment\Event\PaymentTypePreResumeContext;
+use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
+use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface as SymfonyEventDispatcherInterface;
+
+/**
+ * Dispatches Payment events through Symfony's event dispatcher.
+ */
+class SymfonyEventDispatcher implements EventDispatcherInterface {
+
+  /**
+   * The Symfony event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
+   */
+  protected $symfonyEventDispatcher;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $symfony_event_dispatcher
+   */
+  public function __construct(SymfonyEventDispatcherInterface $symfony_event_dispatcher) {
+    $this->symfonyEventDispatcher = $symfony_event_dispatcher;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, array $payment_ids) {
+    $event = new PaymentQueuePaymentIdsAlter($queue_id, $category_id, $owner_id, $payment_ids);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_QUEUE_PAYMENT_IDS_ALTER, $event);
+    $payment_ids = $event->getPaymentIds();
+
+    return $payment_ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPaymentStatus(PaymentInterface $payment, PaymentStatusInterface $previous_payment_status = NULL) {
+    $event = new PaymentStatusSet($payment, $previous_payment_status);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_STATUS_SET, $event);
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preExecutePayment(PaymentInterface $payment) {
+    $event = new PaymentPreExecute($payment);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_EXECUTE, $event);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function executePaymentAccess(PaymentInterface $payment, PaymentMethodInterface $payment_method, AccountInterface $account) {
+    $event = new PaymentExecuteAccess($payment, $payment_method, $account);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_EXECUTE_ACCESS, $event);
+
+    return $event->getAccessResult();
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preCapturePayment(PaymentInterface $payment) {
+    $event = new PaymentPreCapture($payment);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_CAPTURE, $event);
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   */
+  public function preRefundPayment(PaymentInterface $payment) {
+    $event = new PaymentPreRefund($payment);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_PRE_REFUND, $event);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preResumeContext(PaymentInterface $payment) {
+    $event = new PaymentTypePreResumeContext($payment);
+    $this->symfonyEventDispatcher->dispatch(PaymentEvents::PAYMENT_TYPE_PRE_RESUME_CONTEXT, $event);
+  }
+
+}
diff --git a/tests/src/Unit/EventDispatcherCollectionTest.php b/tests/src/Unit/EventDispatcherCollectionTest.php
new file mode 100644
index 0000000..fb89c35
--- /dev/null
+++ b/tests/src/Unit/EventDispatcherCollectionTest.php
@@ -0,0 +1,248 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\payment\Unit\EventDispatcherCollectionTest.
+ */
+
+namespace Drupal\Tests\payment\Unit;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\payment\Entity\PaymentInterface;
+use Drupal\payment\Event\PaymentEvents;
+use Drupal\payment\Event\PaymentExecuteAccess;
+use Drupal\payment\Event\PaymentPreCapture;
+use Drupal\payment\Event\PaymentPreExecute;
+use Drupal\payment\Event\PaymentPreRefund;
+use Drupal\payment\Event\PaymentQueuePaymentIdsAlter;
+use Drupal\payment\Event\PaymentStatusSet;
+use Drupal\payment\Event\PaymentTypePreResumeContext;
+use Drupal\payment\EventDispatcherCollection;
+use Drupal\payment\EventDispatcherInterface;
+use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
+use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
+use Drupal\payment\SymfonyEventDispatcher;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\payment\EventDispatcherCollection
+ *
+ * @group Payment
+ */
+class EventDispatcherCollectionTest extends UnitTestCase {
+
+  /**
+   * The subject under test.
+   *
+   * @var \Drupal\payment\EventDispatcherCollection
+   */
+  protected $sut;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->sut = new EventDispatcherCollection();
+  }
+
+  /**
+   * @covers ::alterQueueLoadedPaymentIds
+   * @covers ::addEventDispatcher
+   */
+  public function testAlterQueueLoadedPaymentIds() {
+    $queue_id = $this->randomMachineName();
+    $category_id = $this->randomMachineName();
+    $owner_id = mt_rand();
+    $payment_ids = [mt_rand(), mt_rand(), mt_rand()];
+    $payment_ids_a = [mt_rand(), mt_rand(), mt_rand()];
+    $payment_ids_b = [mt_rand(), mt_rand(), mt_rand()];
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('alterQueueLoadedPaymentIds')
+      ->with($queue_id, $category_id, $owner_id, $payment_ids)
+      ->willReturn($payment_ids_a);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('alterQueueLoadedPaymentIds')
+      ->with($queue_id, $category_id, $owner_id, $payment_ids_a)
+      ->willReturn($payment_ids_b);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->assertSame($payment_ids_b, $this->sut->alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, $payment_ids));
+  }
+
+  /**
+   * @covers ::setPaymentStatus
+   */
+  public function testSetPaymentStatus() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $previous_payment_status = $this->getMock(PaymentStatusInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('setPaymentStatus')
+      ->with($payment, $previous_payment_status);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('setPaymentStatus')
+      ->with($payment, $previous_payment_status);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->sut->setPaymentStatus($payment, $previous_payment_status);
+  }
+
+  /**
+   * @covers ::preExecutePayment
+   *
+   */
+  public function testPreExecutePayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('preExecutePayment')
+      ->with($payment);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('preExecutePayment')
+      ->with($payment);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->sut->preExecutePayment($payment);
+  }
+
+  /**
+   * @covers ::executePaymentAccess
+   *
+   * @dataProvider providerExecutePaymentAccess
+   *
+   * @param bool|null $expected_access
+   *   TRUE for allowed, NULL for neutral, FALSE for forbidden.
+   * @param \Drupal\Core\Access\AccessResult $event_dispatcher_access_a
+   * @param \Drupal\Core\Access\AccessResult $event_dispatcher_access_b
+   */
+  public function testExecutePaymentAccess($expected_access, AccessResult $event_dispatcher_access_a, AccessResult $event_dispatcher_access_b) {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $payment_method = $this->getMock(PaymentMethodInterface::class);
+
+    $account = $this->getMock(AccountInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('executePaymentAccess')
+      ->with($payment, $payment_method, $account)
+      ->willReturn($event_dispatcher_access_a);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('executePaymentAccess')
+      ->with($payment, $payment_method, $account)
+      ->willReturn($event_dispatcher_access_b);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $access = $this->sut->executePaymentAccess($payment, $payment_method, $account);
+    $this->assertInstanceOf(AccessResultInterface::class, $access);
+    if ($expected_access === TRUE) {
+      $this->assertTrue($access->isAllowed());
+    }
+    elseif ($expected_access === FALSE) {
+      $this->assertTrue($access->isForbidden());
+    }
+    elseif ($expected_access === NULL) {
+      $this->assertTrue($access->isNeutral());
+    }
+  }
+
+  /**
+   * Provides data to self::testExecutePaymentAccess
+   */
+  public function providerExecutePaymentAccess() {
+    return [
+      [TRUE, AccessResult::allowed(), AccessResult::allowed()],
+      [TRUE, AccessResult::allowed(), AccessResult::neutral()],
+      [TRUE, AccessResult::neutral(), AccessResult::allowed()],
+      [NULL, AccessResult::neutral(), AccessResult::neutral()],
+      [FALSE, AccessResult::allowed(), AccessResult::forbidden()],
+      [FALSE, AccessResult::neutral(), AccessResult::forbidden()],
+      [FALSE, AccessResult::forbidden(), AccessResult::allowed()],
+      [FALSE, AccessResult::forbidden(), AccessResult::neutral()],
+      [FALSE, AccessResult::forbidden(), AccessResult::forbidden()],
+    ];
+  }
+
+  /**
+   * @covers ::preCapturePayment
+   */
+  public function testPreCapturePayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('preCapturePayment')
+      ->with($payment);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('preCapturePayment')
+      ->with($payment);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->sut->preCapturePayment($payment);
+  }
+
+  /**
+   * @covers ::preRefundPayment
+   */
+  public function testPreRefundPayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('preRefundPayment')
+      ->with($payment);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('preRefundPayment')
+      ->with($payment);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->sut->preRefundPayment($payment);
+  }
+
+  /**
+   * @covers ::preResumeContext
+   */
+  public function testPreResumeContext() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $event_dispatcher_a = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_a->expects($this->atLeastOnce())
+      ->method('preResumeContext')
+      ->with($payment);
+    $event_dispatcher_b = $this->getMock(EventDispatcherInterface::class);
+    $event_dispatcher_b->expects($this->atLeastOnce())
+      ->method('preResumeContext')
+      ->with($payment);
+
+    $this->sut->addEventDispatcher($event_dispatcher_a);
+    $this->sut->addEventDispatcher($event_dispatcher_b);
+
+    $this->sut->preResumeContext($payment);
+  }
+
+}
diff --git a/tests/src/Unit/EventDispatcherTest.php b/tests/src/Unit/EventDispatcherTest.php
deleted file mode 100644
index 89b66ed..0000000
--- a/tests/src/Unit/EventDispatcherTest.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\payment\Unit\EventDispatcherTest.
- */
-
-namespace Drupal\Tests\payment\Unit;
-
-use Drupal\Core\Access\AccessResultInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\payment\Entity\PaymentInterface;
-use Drupal\payment\Event\PaymentEvents;
-use Drupal\payment\Event\PaymentExecuteAccess;
-use Drupal\payment\Event\PaymentPreCapture;
-use Drupal\payment\Event\PaymentPreExecute;
-use Drupal\payment\Event\PaymentPreRefund;
-use Drupal\payment\Event\PaymentQueuePaymentIdsAlter;
-use Drupal\payment\Event\PaymentStatusSet;
-use Drupal\payment\Event\PaymentTypePreResumeContext;
-use Drupal\payment\EventDispatcher;
-use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
-use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-
-/**
- * @coversDefaultClass \Drupal\payment\EventDispatcher
- *
- * @group Payment
- */
-class EventDispatcherTest extends UnitTestCase {
-
-  /**
-   * The Symfony event dispatcher.
-   *
-   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $symfonyEventDispatcher;
-
-  /**
-   * The class under test.
-   *
-   * @var \Drupal\payment\EventDispatcher
-   */
-  protected $sut;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    $this->symfonyEventDispatcher = $this->getMock(EventDispatcherInterface::class);
-
-    $this->sut = new EventDispatcher($this->symfonyEventDispatcher);
-  }
-
-  /**
-   * @covers ::__construct
-   */
-  public function testConstruct() {
-    new EventDispatcher($this->symfonyEventDispatcher);
-  }
-
-  /**
-   * @covers ::alterQueueLoadedPaymentIds
-   */
-  public function testAlterQueueLoadedPaymentIds() {
-    $queue_id = $this->randomMachineName();
-    $category_id = $this->randomMachineName();
-    $owner_id = mt_rand();
-    $payment_ids = [mt_rand(), mt_rand(), mt_rand()];
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_QUEUE_PAYMENT_IDS_ALTER, $this->isInstanceOf(PaymentQueuePaymentIdsAlter::class));
-
-    $this->assertSame($payment_ids, $this->sut->alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, $payment_ids));
-  }
-
-  /**
-   * @covers ::setPaymentStatus
-   */
-  public function testSetPaymentStatus() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $previous_payment_status = $this->getMock(PaymentStatusInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_STATUS_SET, $this->isInstanceOf(PaymentStatusSet::class));
-
-    $this->sut->setPaymentStatus($payment, $previous_payment_status);
-  }
-
-  /**
-   * @covers ::preExecutePayment
-   *
-   */
-  public function testPreExecutePayment() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_PRE_EXECUTE, $this->isInstanceOf(PaymentPreExecute::class));
-
-    $this->sut->preExecutePayment($payment);
-  }
-
-  /**
-   * @covers ::executePaymentAccess
-   */
-  public function testExecutePaymentAccess() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $payment_method = $this->getMock(PaymentMethodInterface::class);
-
-    $account = $this->getMock(AccountInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_EXECUTE_ACCESS, $this->isInstanceOf(PaymentExecuteAccess::class));
-
-    $this->assertInstanceOf(AccessResultInterface::class, $this->sut->executePaymentAccess($payment, $payment_method, $account));
-  }
-
-  /**
-   * @covers ::preCapturePayment
-   */
-  public function testPreCapturePayment() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_PRE_CAPTURE, $this->isInstanceOf(PaymentPreCapture::class));
-
-    $this->sut->preCapturePayment($payment);
-  }
-
-  /**
-   * @covers ::preRefundPayment
-   */
-  public function testPreRefundPayment() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_PRE_REFUND, $this->isInstanceOf(PaymentPreRefund::class));
-
-    $this->sut->preRefundPayment($payment);
-  }
-
-  /**
-   * @covers ::preResumeContext
-   */
-  public function testPreResumeContext() {
-    $payment = $this->getMock(PaymentInterface::class);
-
-    $this->symfonyEventDispatcher->expects($this->once())
-      ->method('dispatch')
-      ->with(PaymentEvents::PAYMENT_TYPE_PRE_RESUME_CONTEXT, $this->isInstanceOf(PaymentTypePreResumeContext::class));
-
-    $this->sut->preResumeContext($payment);
-  }
-
-}
diff --git a/tests/src/Unit/SymfonyEventDispatcherTest.php b/tests/src/Unit/SymfonyEventDispatcherTest.php
new file mode 100644
index 0000000..f54e856
--- /dev/null
+++ b/tests/src/Unit/SymfonyEventDispatcherTest.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\payment\Unit\SymfonyEventDispatcherTest.
+ */
+
+namespace Drupal\Tests\payment\Unit;
+
+use Drupal\Core\Access\AccessResultInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\payment\Entity\PaymentInterface;
+use Drupal\payment\Event\PaymentEvents;
+use Drupal\payment\Event\PaymentExecuteAccess;
+use Drupal\payment\Event\PaymentPreCapture;
+use Drupal\payment\Event\PaymentPreExecute;
+use Drupal\payment\Event\PaymentPreRefund;
+use Drupal\payment\Event\PaymentQueuePaymentIdsAlter;
+use Drupal\payment\Event\PaymentStatusSet;
+use Drupal\payment\Event\PaymentTypePreResumeContext;
+use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
+use Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface;
+use Drupal\payment\SymfonyEventDispatcher;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * @coversDefaultClass \Drupal\payment\SymfonyEventDispatcher
+ *
+ * @group Payment
+ */
+class SymfonyEventDispatcherTest extends UnitTestCase {
+
+  /**
+   * The Symfony event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $symfonyEventDispatcher;
+
+  /**
+   * The subject under test.
+   *
+   * @var \Drupal\payment\SymfonyEventDispatcher
+   */
+  protected $sut;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->symfonyEventDispatcher = $this->getMock(EventDispatcherInterface::class);
+
+    $this->sut = new SymfonyEventDispatcher($this->symfonyEventDispatcher);
+  }
+
+  /**
+   * @covers ::__construct
+   */
+  public function testConstruct() {
+    new SymfonyEventDispatcher($this->symfonyEventDispatcher);
+  }
+
+  /**
+   * @covers ::alterQueueLoadedPaymentIds
+   */
+  public function testAlterQueueLoadedPaymentIds() {
+    $queue_id = $this->randomMachineName();
+    $category_id = $this->randomMachineName();
+    $owner_id = mt_rand();
+    $payment_ids = [mt_rand(), mt_rand(), mt_rand()];
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_QUEUE_PAYMENT_IDS_ALTER, $this->isInstanceOf(PaymentQueuePaymentIdsAlter::class));
+
+    $this->assertSame($payment_ids, $this->sut->alterQueueLoadedPaymentIds($queue_id, $category_id, $owner_id, $payment_ids));
+  }
+
+  /**
+   * @covers ::setPaymentStatus
+   */
+  public function testSetPaymentStatus() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $previous_payment_status = $this->getMock(PaymentStatusInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_STATUS_SET, $this->isInstanceOf(PaymentStatusSet::class));
+
+    $this->sut->setPaymentStatus($payment, $previous_payment_status);
+  }
+
+  /**
+   * @covers ::preExecutePayment
+   *
+   */
+  public function testPreExecutePayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_PRE_EXECUTE, $this->isInstanceOf(PaymentPreExecute::class));
+
+    $this->sut->preExecutePayment($payment);
+  }
+
+  /**
+   * @covers ::executePaymentAccess
+   */
+  public function testExecutePaymentAccess() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $payment_method = $this->getMock(PaymentMethodInterface::class);
+
+    $account = $this->getMock(AccountInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_EXECUTE_ACCESS, $this->isInstanceOf(PaymentExecuteAccess::class));
+
+    $this->assertInstanceOf(AccessResultInterface::class, $this->sut->executePaymentAccess($payment, $payment_method, $account));
+  }
+
+  /**
+   * @covers ::preCapturePayment
+   */
+  public function testPreCapturePayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_PRE_CAPTURE, $this->isInstanceOf(PaymentPreCapture::class));
+
+    $this->sut->preCapturePayment($payment);
+  }
+
+  /**
+   * @covers ::preRefundPayment
+   */
+  public function testPreRefundPayment() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_PRE_REFUND, $this->isInstanceOf(PaymentPreRefund::class));
+
+    $this->sut->preRefundPayment($payment);
+  }
+
+  /**
+   * @covers ::preResumeContext
+   */
+  public function testPreResumeContext() {
+    $payment = $this->getMock(PaymentInterface::class);
+
+    $this->symfonyEventDispatcher->expects($this->once())
+      ->method('dispatch')
+      ->with(PaymentEvents::PAYMENT_TYPE_PRE_RESUME_CONTEXT, $this->isInstanceOf(PaymentTypePreResumeContext::class));
+
+    $this->sut->preResumeContext($payment);
+  }
+
+}
