Question

I have a Slim application that has some Middleware.

It performs authentication for the route, and retrieves the route like so:

$route = $this->getApplication()->router()->getCurrentRoute();

I'm now testing it and am attempting to use Mockery to mock the result of the chained call, so I can effectively specify the route.

$mock = M::mock('\Api\SessionMiddleware[getApplication]');
$mock->shouldReceive('router->getCurrentRoute')->andReturn('myRoute');

This doesn't work. It tries to call: require('lib/demeter/router.php') and fails as this doesn't exist.

I've also tried:

$mock = M::mock('\Api\SessionMiddleware')->shouldDeferMissing();
$mock->shouldReceive('getApplication->router->getCurrentRoute')->andReturn('myRoute');

This doesn't work either, failing with:

Failed opening required 'lib/demeter/getApplication.php'

What am I missing?

Was it helpful?

Solution 2

You also need to mock the router. and let the router() method return the router mock in turn.

$mock = M::mock('\Api\SessionMiddleware[getApplication]');
$routerMock = M::mock('My\Router');
$routerMock->shouldReceive('getCurrentRoute')->andReturn('myRoute');
$mock->shouldReceive('router')->andReturn($routerMock);

OTHER TIPS

Even though there's an accepted answer, I wanted to provide future users with another solution.

There should be no need to mock the router if it's only used as an intermediate step of the demeter chain. Try this:

$mock = M::mock('\Api\SessionMiddleware');
$mock->shouldReceive('getApplication->router->getCurrentRoute')->andReturn('myRoute');

The key is removing the call to shouldDeferMissing(), which in this case seems to interfere with the demeter chain.

This way, a "pure" mock, which doesn't forward anything to the real implementation of SessionMiddleware, is returned. It should be able to reply with 'myRoute' when $mock->getApplication()->getRouter()->getCurrentRoute() is invoked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top