PHPUnit and ZF2 Services
Asked Answered
C

1

7

I have a little problem when creating tests with PHPUnit.

Here is my setup :

protected function setUp()
{
    $serviceManager = Bootstrap::getServiceManager();

    $this->mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface');
    $this->mockConnection = $this->getMock('Zend\Db\Adapter\Driver\ConnectionInterface');
    $this->mockDriver->expects($this->any())->method('checkEnvironment')->will($this->returnValue(true));
    $this->mockDriver->expects($this->any())->method('getConnection')->will($this->returnValue($this->mockConnection));
    $this->mockPlatform = $this->getMock('Zend\Db\Adapter\Platform\PlatformInterface');
    $this->mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface');
    $this->mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($this->mockStatement));
    $this->adapter = new Adapter($this->mockDriver, $this->mockPlatform);
    $this->sql = new Sql($this->adapter);

    $mockTableGateway = $this->getMock('Zend\Db\TableGateway\TableGateway', array(), array(), '', false);

    $maiFormuleRevisionTable = $this->getMockBuilder('Maintenance\Model\BDD\PMaiFormulerevisionTable')
        ->setMethods(array())
        ->setConstructorArgs(array($mockTableGateway, $this->adapter, $this->sql))
        ->getMock();
    $maiFormulerevisionService = $this->getMockBuilder('Maintenance\Service\Model\PMaiFormulerevisionService')
        ->setMethods(array())
        ->setConstructorArgs(array($maiFormuleRevisionTable))
        ->getMock();
    $this->assertTrue($maiFormulerevisionService instanceof PMaiFormulerevisionService);

    $this->controller = new RevisionsController($maiFormulerevisionService);

    $this->request    = new Request();
    $this->routeMatch = new RouteMatch(array('controller' => 'index'));
    $this->event      = new MvcEvent();
    $config = $serviceManager->get('Config');
    $routerConfig = isset($config['router']) ? $config['router'] : array();
    $router = HttpRouter::factory($routerConfig);
    $this->event->setRouter($router);
    $this->event->setRouteMatch($this->routeMatch);
    $this->controller->setEvent($this->event);
    $this->controller->setServiceLocator($serviceManager);
}

Here is the test for my function :

public function testEditFormuleActionCanBeAccessed()
{
    $this->routeMatch->setParam('action', 'loadformule');
    $this->routeMatch->setParam('idformule', '23');
    $result   = $this->controller->dispatch($this->request);
    $response = $this->controller->getResponse();
    $this->assertEquals(200, $response->getStatusCode());
}

And my Controler :

public function loadformuleAction()
{
    try {
        $iStatus = 0;
        $iMaiFormuleRevisionId = (int) $this->params('idformule');

        $oFormule = $this->maiFormulerevisionService->selectByIdOrCreate($iMaiFormuleRevisionId);
        $maiFormulerevisionForm = new PMaiFormulerevisionForm($oFormule);

        if ($this->getRequest()->isPost()) {
            /* etc ... */
        }

        $viewModel = new ViewModel();
        $viewModel->setTerminal(true);
        $viewModel->setVariables([
            'maiFormulerevisionForm' => $maiFormulerevisionForm,
            'iMaiFormuleRevisionId'  => $oFormule->getMaiFormuleRevisionId(),
            'iStatus'                => $iStatus
        ]);
        return $viewModel;
    } catch (\Exception $e) {
        throw new \Exception($e);
    }
}

But when I try to run my test, it shows an error, and I point that my test don't go into my service, when I call it ($this->maiFormulerevisionService) :

1) MaintenanceTest\Controller\RevisionsControllerTest::testEditFormuleActionCanBeAccessed Exception: Argument 1 passed to Maintenance\Form\PMaiFormulerevisionForm::__construct() must be an instance of Maintenance\Model\PMaiFormulerevision, null given

I don't understand why my mock doesn't work ...

Thanks for your answers :)

Edit :

Hum ... when I try this :

$maiFormulerevisionService = new PMaiFormulerevisionService($maiFormuleRevisionTable);

Instead of this :

$maiFormulerevisionService = $this->getMockBuilder('Maintenance\Service\Model\PMaiFormulerevisionService')
            ->setMethods(array())
            ->setConstructorArgs(array($maiFormuleRevisionTable))
            ->getMock();

It goes into the service but not into the TableGateway specified in the constructor of the service ($maiFormuleRevisionTable) ... so it still doesn't work ...

Cultivated answered 7/9, 2015 at 12:40 Comment(4)
Please i'm really blocked. I really need to solve this mock problem and the documentation is really soft !Cultivated
Not tested but it looks like you are creating a mock for maiFormulerevisionService that returns null for all methods. So in your controller, this will return null $oFormule = $this->maiFormulerevisionService->selectByIdOrCreate($iMaiFormuleRevisionId); Which means this will be passed null in the constructor, which is your error message $maiFormulerevisionForm = new PMaiFormulerevisionForm($oFormule);Glycol
I tested but the method on test mode don't go into selectByIdOrCreate() function in fact, so it does not return null ... well, in fact it doesn't go into services, or datagateway classes ...Cultivated
It would be useful to show the constructor for your controller here.Jocund
B
2

You set a mock, but you also have to set what your mock returns when calling the method selectByIdOrCreate. Since you do:

$oFormule = $this->maiFormulerevisionService->selectByIdOrCreate($iMaiFormuleRevisionId);
$maiFormulerevisionForm = new PMaiFormulerevisionForm($oFormule);

The mock will return null for the selectByIdOrCreate method as long as you don't set a return value for this method.

Try to add a mock method like this:

$mock = $maiFormulerevisionService;
$methodName = 'selectByIdOrCreate';
$stub = $this->returnValue($maiFormuleRevisionTable);

$mock->expects($this->any())->method($methodName)->will($stub);
Barcroft answered 10/9, 2015 at 15:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.