Search code examples
zend-framework2phpunitzend-test

Type Error exception while unit testing (zend-test, PHPUnit)


I am trying to test a simple controller action in Zend FrameWork and I am not 100% sure why my mocks are not working.

Original Action:

 public function overviewAction()
    {
        $page = $this->params()->fromQuery('page', 1);
        $count = 10;

        $user = $this->authenticationService->getIdentity();

        return new ViewModel([
            'paginator' => $this->agentService->getAgentsOwnedByUser($page, $count, $user),
        ]);
    }

My Test for this action

    /**
     * Set Rbac Role and route
     */
    $url = "cp/agent";
    $this->setRbacGuards(['admin']);
    //Nb Rbac class code is here

    /**
     * Objects required in this test
     */
    $user = $this->createMock(User::class);
    $paginator = $this->createMock(Paginator::class);

    /**
     * Mock classes and their methods to be called
     */
    $authentication = $this->createMock(AuthenticationService::class);
    $authentication
        ->expects($this->once())
        ->method('getIdentity')
        ->will($this->returnValue($this->registerMockObject($user)));


    $agentService = $this->createMock(AgentService::class);
    $agentService
        ->expects($this->once())
        ->method('getAgentsOwnedByUser')
        ->will($this->returnValue($this->registerMockObject($paginator)));

    $this->dispatch('/'.$url);
    $this->assertResponseStatusCode(200);

The error message

 There was 1 failure:

    1) ControlPanelTest\Controller\AgentControllerTest::testAgentOverviewActionCanBeAccessed
    Failed asserting response code "200", actual status code is "500"

    Exceptions raised:
    Exception 'TypeError' with message 'Argument 3 passed to 

    Admin\Service\AgentService::getAgentsOwnedByUser() must be an instance of Domain\User\User, null given
.

For completeness, Rbac Class

public function rbacGuards($roles)
    {
        /**
         * Deal with Rbac Guards
         */
        $roleService = $this->getApplicationServiceLocator()->get(RoleService::class);
        $identityProvider = $this->prophesize(IdentityProviderInterface::class);
        $identity = $this->prophesize(IdentityInterface::class);
        // Here you use the setter to inject your mocked identity provider
        $roleService->setIdentityProvider($identityProvider->reveal());
        $identityProvider->getIdentity()->shouldBeCalled()->willReturn($identity->reveal());
        $identity->getRoles()->shouldBeCalled()->willReturn($roles);
    }

Prognosis

It seems the mocks are not being called...


Solution

  • In your example, you create $authentication mock, but you don't register it as property of class you are testing. Thus, when overviewAction is using $this->authenticationService->getIdentity();, it is not using the mock you created.