# Unit test failing for the paginated module

**URL:** https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593
**Category:** Components & MVC
**Tags:** laminas-paginator, laminas-test
**Created:** [February 9, 2024, 6:37am UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593 "2024-02-09T06:37:20Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![vrkansagara](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/vrkansagara/32/82_2.png) [@vrkansagara](https://discourse.laminas.dev/u/vrkansagara)
#### Post date: [February 9, 2024, 6:37am UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593/1 "2024-02-09T06:37:20Z")

</div>

I was trying to follow this tutorial with the pagination + unit test , it is failing and not sure how to fix it. Can any one help me . thanks in advance

> **[Unit Testing A laminas-mvc Application - tutorials - Laminas Docs](https://docs.laminas.dev/tutorials/unit-testing/)**
>
> Learn how to create laminas-mvc applications, get in-depth guides into components, and discover how to migrate your applications to version 3!

 ![image](https://canada1.discourse-cdn.com/flex032/uploads/zendframework/original/2X/0/0b383132b578a478acd758e5e08212d16fe163b7.png)

AlbumController.php

```auto
<?php

namespace Album\Controller;

use Album\Model\AlbumTable;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
use Album\Form\AlbumForm;
use Album\Model\Album;

class AlbumController extends AbstractActionController
{
  // Add this property:
    private $table;

  // Add this constructor:
    public function __construct(AlbumTable $table)
    {
        $this->table = $table;
    }

    public function indexAction()
    {
      // Grab the paginator from the AlbumTable:
        $paginator = $this->table->fetchAll(true);

      // Set the current page to what has been passed in query string,
      // or to 1 if none is set, or the page is invalid:
        $page = (int) $this->params()->fromQuery('page', 1);
        $page = ($page < 1) ? 1 : $page;
        $paginator->setCurrentPageNumber($page);

      // Set the number of items per page to 10:
        $paginator->setItemCountPerPage(10);

        return new ViewModel(['paginator' => $paginator]);
    }

    public function addAction()
    {
        $form = new AlbumForm();
        $form->get('submit')->setValue('Add');

        $request = $this->getRequest();

        if (! $request->isPost()) {
            return ['form' => $form];
        }

        $album = new Album();
        $form->setInputFilter($album->getInputFilter());
        $form->setData($request->getPost());

        if (! $form->isValid()) {
            return ['form' => $form];
        }

        $album->exchangeArray($form->getData());
        $this->table->saveAlbum($album);
        return $this->redirect()->toRoute('album');
    }

    public function editAction()
    {
        $id = (int) $this->params()->fromRoute('id', 0);

        if (0 === $id) {
            return $this->redirect()->toRoute('album', ['action' => 'add']);
        }

      // Retrieve the album with the specified id. Doing so raises
      // an exception if the album is not found, which should result
      // in redirecting to the landing page.
        try {
            $album = $this->table->getAlbum($id);
        } catch (\Exception $e) {
            return $this->redirect()->toRoute('album', ['action' => 'index']);
        }

        $form = new AlbumForm();
        $form->bind($album);
        $form->get('submit')->setAttribute('value', 'Edit');

        $request = $this->getRequest();
        $viewData = ['id' => $id, 'form' => $form];

        if (! $request->isPost()) {
            return $viewData;
        }

        $form->setInputFilter($album->getInputFilter());
        $form->setData($request->getPost());

        if (! $form->isValid()) {
            return $viewData;
        }

        try {
            $this->table->saveAlbum($album);
        } catch (\Exception $e) {
        }

      // Redirect to album list
        return $this->redirect()->toRoute('album', ['action' => 'index']);
    }

    public function deleteAction()
    {
        $id = (int) $this->params()->fromRoute('id', 0);
        if (! $id) {
            return $this->redirect()->toRoute('album');
        }

        $request = $this->getRequest();
        if ($request->isPost()) {
            $del = $request->getPost('del', 'No');

            if ($del == 'Yes') {
                $id = (int) $request->getPost('id');
                $this->table->deleteAlbum($id);
            }

          // Redirect to list of albums
            return $this->redirect()->toRoute('album');
        }

        return [
        'id' => $id,
        'album' => $this->table->getAlbum($id),
        ];
    }
}

```

AlbumControllerTest.php

```auto

<?php

namespace AlbumTest\Controller;

use Album\Controller\AlbumController;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;

class AlbumControllerTest extends AbstractHttpControllerTestCase
{
    use ProphecyTrait;

    protected $traceError = true;

    protected $albumTable;

    protected function setUp(): void
    {
      // The module configuration should still be applicable for tests.
      // You can override configuration here with test case specific values,
      // such as sample view templates, path stacks, module_listener_options,
      // etc.
        $configOverrides = [];

        $applicationConfigPath = realpath( __DIR__. '/../../../../config/application.config.php');

        $this->setApplicationConfig(ArrayUtils::merge(// Grabbing the full application configuration:
            include $applicationConfigPath,
            $configOverrides
        ));
        parent::setUp();

        $this->configureServiceManager($this->getApplicationServiceLocator());
    }

    public function testIndexActionCanBeAccessed()
    {

        $this->albumTable->fetchAll()->willReturn([]);

        $this->dispatch('/album');
        $this->assertResponseStatusCode(200);
        $this->assertModuleName('Album');
        $this->assertControllerName(AlbumController::class);
        $this->assertControllerClass('AlbumController');
        $this->assertMatchedRouteName('album');
    }

    public function TestIndexActionCanNotBeAccessedDB()
    {
        $services = $this->getApplicationServiceLocator();
        $config = $services->get('config');
        unset($config['db']);
        $services->setAllowOverride(true);
        $services->setService('config', $config);
        $services->setAllowOverride(false);

        $this->dispatch('/album');
        $this->assertResponseStatusCode(200);
        $this->assertModuleName('Album');
        $this->assertControllerName(AlbumController::class);
        $this->assertControllerClass('AlbumController');
        $this->assertMatchedRouteName('album');
    }

    protected function configureServiceManager(ServiceManager $services)
    {
        $services->setAllowOverride(true);

        $services->setService('config', $this->updateConfig($services->get('config')));
        $services->setService(AlbumTable::class, $this->mockAlbumTable()->reveal());

        $services->setAllowOverride(false);
    }

    protected function updateConfig($config)
    {
        $config['db'] = [];
        return $config;
    }

    protected function mockAlbumTable()
    {
        $this->albumTable = $this->prophesize(AlbumTable::class);
        return $this->albumTable;
    }

    public function testAddActionRedirectsAfterValidPost()
    {
        $this->albumTable
        ->saveAlbum(Argument::type(Album::class))
        ->shouldBeCalled();

        $postData = [
        'title' => 'Led Zeppelin III',
        'artist' => 'Led Zeppelin',
        'id' => '',
        ];
        $this->dispatch('/album/add', 'POST', $postData);
        $this->assertResponseStatusCode(302);
        $this->assertRedirectTo('/album');
    }
}

```

Module.php

```auto
<?php

namespace Album;

use Laminas\Db\Adapter\AdapterInterface;
use Laminas\Db\ResultSet\ResultSet;
use Laminas\ModuleManager\Feature\ConfigProviderInterface;
use Laminas\Db\TableGateway\TableGateway;

class Module implements ConfigProviderInterface {

  public function getConfig() {
    return include __DIR__. '/../config/module.config.php';
  }

  // Add this method:
  public function getServiceConfig() {
    return [
      'factories' => [
        Model\AlbumTable::class => function($container) {
          $tableGateway = $container->get(Model\AlbumTableGateway::class);

          return new Model\AlbumTable($tableGateway);
        },
        Model\AlbumTableGateway::class => function($container) {
          $dbAdapter = $container->get(AdapterInterface::class);
          $resultSetPrototype = new ResultSet();
          $resultSetPrototype->setArrayObjectPrototype(new Model\Album());

          return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
        },
      ],
    ];
  }

  public function getControllerConfig() {
    return [
      'factories' => [
        Controller\AlbumController::class => function($container) {
          return new Controller\AlbumController($container->get(Model\AlbumTable::class));
        },
      ],
    ];
  }
}

```

This code is perfectly working fine while I run through the browser and navigate to `/album` and all the operation is working perfect like add. edit and delete and pagination as well but it fails for the unit test caese

---

<div class="post-metadata">

### Author: ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)
#### Post date: [February 9, 2024, 8:35am UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593/2 "2024-02-09T08:35:18Z")

</div>

> [@vrkansagara](#):
>
> I was trying to follow this tutorial with the pagination + unit test , it is failing and not sure how to fix it.

The current result is correct, because if the paginator is added, the tests can no longer be run as before.

Because the `AlbumTable` class no longer returns an array here:

```php
public function testIndexActionCanBeAccessed()
{
    $this->albumTable->fetchAll()->willReturn([]);

    // …
}

```

If the parameter for pagination is set to `true`, a paginator is returned:

```php
public function fetchAll($paginated = false)
{
    if ($paginated) {
        return $this->fetchPaginatedResults();
    }

    return $this->tableGateway->select();
}

private function fetchPaginatedResults()
{
    // …

    return new Paginator($paginatorAdapter);
}

```

This also needs to be changed in your tests. The [`ArrayAdapter` of laminas-paginator](https://docs.laminas.dev/laminas-paginator/usage/#paginating-data-collections) can help in tests.

References:

- [Unit Testing A laminas-mvc Application - tutorials - Laminas Docs](https://docs.laminas.dev/tutorials/unit-testing/#configuring-the-service-manager-for-the-tests)
- [Adding laminas-paginator to the Album Module - tutorials - Laminas Docs](https://docs.laminas.dev/tutorials/pagination/#modifying-the-albumtable)
- [Adding laminas-paginator to the Album Module - tutorials - Laminas Docs](https://docs.laminas.dev/tutorials/pagination/#modifying-the-albumcontroller)

---

<div class="post-metadata">

### Author: ![vrkansagara](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/vrkansagara/32/82_2.png) [@vrkansagara](https://discourse.laminas.dev/u/vrkansagara)
#### Post date: [February 9, 2024, 4:35pm UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593/3 "2024-02-09T16:35:51Z")

</div>

> [@froschdesign](#):
>
> `fetchAll`

Here is :- AlbumTable.php code

I also followed this article . [Adding laminas-paginator to the Album Module - tutorials - Laminas Docs](https://docs.laminas.dev/tutorials/pagination/) for the pagination album module

```auto
<?php

namespace Album\Model;

use RuntimeException;
use Laminas\Db\TableGateway\TableGatewayInterface;
use Laminas\Db\ResultSet\ResultSet;
use Laminas\Db\Sql\Select;
use Laminas\Paginator\Adapter\DbSelect;
use Laminas\Paginator\Paginator;

class AlbumTable
{
    private $tableGateway;

    public function __construct(TableGatewayInterface $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }

    public function fetchAll($paginated = false)
    {
        if ($paginated) {
            return $this->fetchPaginatedResults();
        }

        return $this->tableGateway->select();
    }

    private function fetchPaginatedResults()
    {
      // Create a new Select object for the table:
        $select = new Select($this->tableGateway->getTable());

      // Create a new result set based on the Album entity:
        $resultSetPrototype = new ResultSet();
        $resultSetPrototype->setArrayObjectPrototype(new Album());

      // Create a new pagination adapter object:
        $paginatorAdapter = new DbSelect(
      // our configured select object:
            $select,
            // the adapter to run it against:
            $this->tableGateway->getAdapter(),
            // the result set to hydrate:
            $resultSetPrototype
        );

        return new Paginator($paginatorAdapter);
    }

    public function getAlbum($id)
    {
        $id = (int)$id;
        $rowset = $this->tableGateway->select(['id' => $id]);
        $row = $rowset->current();
        if (! $row) {
            throw new RuntimeException(sprintf(
                'Could not find row with identifier %d',
                $id
            ));
        }

        return $row;
    }

    public function saveAlbum(Album $album)
    {
        $data = [
        'artist' => $album->artist,
        'title' => $album->title,
        ];

        $id = (int)$album->id;

        if ($id === 0) {
            $this->tableGateway->insert($data);

            return;
        }

        try {
            $this->getAlbum($id);
        } catch (RuntimeException $e) {
            throw new RuntimeException(sprintf(
                'Cannot update album with identifier %d; does not exist',
                $id
            ));
        }

        $this->tableGateway->update($data, ['id' => $id]);
    }

    public function deleteAlbum($id)
    {
        $this->tableGateway->delete(['id' => (int)$id]);
    }
}

```

---

<div class="post-metadata">

### Author: ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)
#### Post date: [February 12, 2024, 10:10am UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593/4 "2024-02-12T10:10:37Z")

</div>

There is another problem: you have created a method called `mockAlbumTable` and set the result of this method as a service for the application, but you do not use this in your tests.

---

<div class="post-metadata">

### Author: ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)
#### Post date: [February 12, 2024, 10:11am UTC](https://discourse.laminas.dev/t/unit-test-failing-for-the-paginated-module/3593/5 "2024-02-12T10:11:55Z")

</div>

Regardless of this, I recommend that you look at and use [Mezzio](https://docs.mezzio.dev/mezzio/). It is easier and more open to use.
