swaechter
swaechter

Reputation: 1439

How to dynamically mock the Zfc User service

Situation: I am testing a Zend controller action, where a user has to login or otherwise will get redirected:

<?php

namespace MyModule\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class GameController extends AbstractActionController
{
    public function indexAction()
    {
        if ($this->zfcUserAuthentication()->hasIdentity()) {
            $view = new ViewModel();
            $user = $this->zfcUserAuthentication()->getIdentity();
            $view->username = $user->getUsername();
            return $view;
        } else {
            $this->redirect()->toRoute("mymodule/overview");
        }
    }
}

My test case then looks like this:

<?php

namespace MyModuleTest\Controller;

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
use ZfcUser\Controller\Plugin\ZfcUserAuthentication;
use ZfcUser\Entity\User;

class GameControllerTest extends AbstractHttpControllerTestCase
{
    public function setUp()
    {
        $this->setApplicationConfig(include __DIR__ . '/../../../../../config/application.config.php');
        parent::setUp();
    }

    public function testIndexAction()
    {
        // Mock the authentication user
        $user = $this->createMock(User::class);
        $user->expects($this->any())->method('getId')->will($this->returnValue('1'));

        // Mock the authentication adapter
        $authentication = $this->createMock(ZfcUserAuthentication::class);
        $authentication->expects($this->any())->method('hasIdentity')->will($this->returnValue(true));
        $authentication->expects($this->any())->method('getIdentity')->will($this->returnValue($user));

        $this->dispatch('/mymodule/game');
        $this->assertResponseStatusCode(302);
        $this->assertModuleName('MyModule');
        $this->assertMatchedRouteName('mymodule/game');
        $this->assertControllerName('MyModule\Controller\Game');
        $this->assertControllerClass('GameController');
        $this->assertActionName('index');

        // TODO: Log in the user
        // How do I install the mocked Zfc authentication?

        $this->dispatch('/mymodule/game');
        $this->assertResponseStatusCode(200);
        $this->assertModuleName('MyModule');
        $this->assertMatchedRouteName('mymodule/game');
        $this->assertControllerName('MyModule\Controller\Game');
        $this->assertControllerClass('GameController');
        $this->assertActionName('index');
    }
}

Problem: There are a few StackOverflow posts how to mock the ZfcUser authentication service, but how can I do this dynamically (Working code example)? First, I want to trigger the redirect (and check for the 302 HTTP code), then I want to login the user (mock it) and check it again (and receive a 200 HTTP code)

Upvotes: 0

Views: 112

Answers (1)

Wilt
Wilt

Reputation: 44422

You should mock the ZfcUser service in your tests. Testing the working of ZfcUser falls outside the scope of your application and is done in the tests for the ZfcUser module. For example here for 302 errors:

ZfcUser/tests/ZfcUserTest/Controller/RedirectCallbackTest.php ZfcUser/src/ZfcUser/Controller/RedirectCallback.php ZfcUser/tests/ZfcUserTest/Controller/UserControllerTest.php

UPDATE:

So your $this->zfcUserAuthentication() method should return the mocked class that you prepared. This part of your code is not in the question, so I cannot give you more details on this. Best would be to have the ZfcUser authentication service injected through constructor dependency injection (as a dependency in your class constructor).

Upvotes: 0

Related Questions