Functional Testing Events and Subscribers in Symfony 4
Asked Answered
V

1

6

I need to functionally test the a subscriber in Symfony 4 and I'm having problems finding how. The Subscriber has the following structure

/**
* Class ItemSubscriber
*/
class ItemSubscriber implements EventSubscriberInterface
{
    /**
     * @var CommandBus
     */
    protected $commandBus;

    /**
     * Subscriber constructor.
     *
     * @param CommandBus $commandBus
     */
    public function __construct(CommandBus $commandBus)
    {
        $this->commandBus = $commandBus;
    }

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            CommandFailedEvent::NAME => 'onCommandFailedEvent',
        ];
    }

    /**
     * @param CommandFailedEvent $event
     *
     * @throws Exception
     */
    public function onCommandFailedEvent(CommandFailedEvent $event)
    {
        $item = $event->getItem();
        $this->processFailed($item);
    }

    /**
     * Sends message 
     *
     * @param array $item
     *
     * @throws Exception
     */
    private function processFailed(array $item)
    {
        $this->commandBus->handle(new UpdateCommand($item));
    }
}

The flow of the subscriber is receiving an internal event and send a message by rabbit through the command bus to another project.

How can I test that dispatching the event CommandFailedEvent the line in processFailed(array $item) is executed?

Does anyone has documentation on best practices to test Events and Subscribers in Symfony 4?

Vamp answered 5/3, 2020 at 9:1 Comment(0)
L
4

If you want to test the process of a command bus handler being call you could test dependency method calls thanks to mock expects. You have some examples in the PHPUnit documentation.

For instance, you would have something like:

$commandBus = $this->getMockBuilder(CommandBus::class)->disableOriginalConstructor()->getMock();
$commandBus->expects($this->once())->method('handle');

// Create your System Under Test
$SUT = new CommandFailedSubscriber($commandBus);

// Create event
$item = $this->getMockBuilder(YourItem::class)->getMock();
$event = new CommandFailedEvent($item);

// Dispatch your event
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber($SUT);
$dispatcher->dispatch($event);

I hope this would be enough for you to explore possibilities and to have the coverage needed for your feature.

Have a nice time testing!

Lighthearted answered 5/3, 2020 at 9:47 Comment(3)
What do you mean by $mailer in the new CommandFailedSubscriber($mailer) I'm trying to implement this solution and variations. but I'm having difficulties. It seems the subscriber is not receiving the command.Vamp
It was an error in variable name because I adapted this example from an existing case. Sorry! In your test case, you would have access to a CommandBus&MockObject instance passed to your ItemSubscriber class. Your dispatch action must be adapted to your case $dispatcher->dispatch($event, CommandFailedEvent::NAME); or in reverse order depending of your EventDispatcherComponent package version. :) I don't now if I could be clearer without the specific PHPUnit failure message.Lighthearted
This is a unit test, but at the moment is the best way I found to test the subscriber.Vamp

© 2022 - 2024 — McMap. All rights reserved.