How to test PipelineAndRoutesDelegator?

Hello everybody,

in the expressive cookbook there is a post on how to autowire routes and pipelines (https://zendframework.github.io/zend-expressive/cookbook/autowiring-routes-and-pipelines).

I wonder if and how this could be tested with phpunit.

Thanks in advance and cheers,
Lowtower.

I guess there are multiple ways to test it. One of them would be to init the application and check each of the of they exist in the application. You can grab all routes with $app->getRoutes().

Other one would be like a smoke test and try to load each route. If you get a 404 it’s not working.

What I’ve done in the past is mock the Zend\Expressive\Application class, and have the $callback passed to the delegator return the mock. That way I can add expectations to the mock for the various routes and/or pipeline calls made on the application instance.

Thanks a lot for Your suggestions!

I am just starting with unit tests.
At first, I tried the smoke test, but didn’t succeed.
Then I thought about @matthew’s suggestion, but I don’ know how to

have the $callback passed to the delegator return the mock

I know how to get mock objects and I know how to let mocks return something, but I don’t know how to handle callbacks.

Could You please explain a bit deeper, e.g. with code?

Thanks in advance,
LT.

Sure!

Let’s say you have the following delegator factory registering a single route:

namespace Acme;

use Psr\Container\ContainerInterface;

class HomeRouteDelegatorFactory
{
    public function __invoke(ContainerInterface $container, $serviceName, callable $callback)
    {
        $app = $callback();
        $app->get('/', Action\HomePageAction::class, 'home');
        return $app;
    }
}

You could write a test like the following:

<?php
namespace AcmeTest;

use Acme\Action\HomePageAction;
use Acme\HomeRouteDelegatorFactory;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Zend\Expressive\Application;

class HomeRouteDelegatorFactoryTest extends TestCase
{
    public function testRegistersHomePageRoute()
    {
        $container = $this->prophesize(ContainerInterface::class)->reveal();

        $app = $this->prophesize(Application::class);
        $app->get('/', HomePageAction::class, 'home')->shouldBeCalled();
        $callback = function () use ($app) {
            return $app->reveal();
        };

        $delegator = new HomeRouteDelegatorFactory();

        $result = $delegator($container, Application::class, $callback);

        $this->assertSame($app->reveal(), $result);
    }
}

The above mocks the Application class, writes expectations against it, and
then creates a callback that will return it. This is passed to the delegator,
and we can then verify the Application is what is returned.

Great, thanks a lot :slight_smile: