Unit Testing Zend Expressive Database Classes with Codeception

Using Codeception as your testing framework of choice? Did you know it’s really easy to test Zend Expressive TableGateway classes? It’s almost painfully easy. This tutorial walks you through, step-by-step.


“Unit Testing Zend Expressive Database Classes with Codeception”

Using Codeception as your testing framework of choice? Did you know it’s really easy to test Zend Expressive TableGateway classes? It’s almost painfully easy. This tutorial walks you through, step-by-step.

But first, why would you want to do database testing? After all, even the PhpUnit manual suggests that database testing isn’t easy; primarily because you need to take care of the following things:

  1. The database schema and tables
  2. Inserting the rows required for the test into these tables
  3. Verifying the state of the database after your test has run
  4. Cleanup the database for each new test

If you’ve ever tried to do it before, you’ll know that it isn’t easy, especially if you’re integrating it into a project which has loads of existing tests, but hasn’t had database testing so far.

Actually, it can start to push you round the twist, like it was for me, if you’re not used to it. But, with a little discipline and determination, using Codeception, and a recent module for Zend Expressive, you’re all sorted!

In a nutshell, there’s only 5 things you need to do. Let’s work through them.

1. Configure the Database Dump File

One of the core features of Codeception is to be able to run a database dump file on your configured database, by default called tests/_data/dump.sql before each test, and optionally clean up afterwards. So let’s do that first.

If you don’t have a database dump of your database, make one and store it there. Assuming that you’re using MySQL, run the command mysqldump db_name > db.dump.sql which will create the dump file.

Alternatively, you can use tools such as Navicat, which have excellent GUIs and make the task of creating dump files, virtually, painless.

After that, you need to update the Codeception configuration files to load the dump file, and clean up afterwards. Here’s how to do that. In tests/unit.suite.yml ensure there’s a Db configuration section, similar to that below.

class_name: UnitTester
modules:
    enabled:
        - Asserts
        - \Helper\Unit
        - Db:
            dsn: 'pgsql:host=localhost;port=5432;dbname=database_name'
            user: ‘user_name'
            password: ‘my_password’
            dump: tests/_data/dump.sql
            cleanup: true
            populate: true

This will load the database with the data from tests/_data/dump.sql before each test, and clean it up after each test.

2. Enable the Zend Expressive Module

With the dump file configured, we now need to load the Zend Expressive Codeception module. To do that, open tests/unit.suite.yml and add ZendExpressive to the list of enabled modules. Here’s a sample of what it may look like, depending on your configuration.

class_name: UnitTester
modules:
    enabled:
        - Asserts
        - \Helper\Unit
        - ZendExpressive

3. Create a Unit Test

Now that we have everything in place, it’s time to create a test which will work with your database. To do that, run the following command php vendor/bin/codecept generate:test unit TableGateway/UsersTableGatewayTest. This will generate a new, empty, unit test under tests/unit/TableGateway, creating the TableGateway directory if it doesn’t exist. It will, initially, look like the following:

<?php

namespace TelcoSwitchTests\Unit;

class UsersTableGatewayTest extends \Codeception\TestCase\Test
{
    protected $tester;

    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testMe()
    {

    }
}

Now we need to create a local variable which will be an instance of our database service. To do that, add a new member variable, called usersTable. To instantiate it, we’ll then implement the _before() method, which runs before all the tests.

There, we’ll use the ZendExpressive module to get access to the application’s DI container, and retrieve the UserTable service - which is our TableGateway class which interacts with the user table. It will look as follows:

protected function _before()
{
    $this->usersTable = $this->getModule('ZendExpressive')
        ->container
        ->get(UserTable::class);
}

With this done, we’re now ready to start calling the methods on it.

4. Add Your Test

Let’s say that we have a method on that class, which retrieves a user by their id, a method which is defined as follows:

    /**
     * @param int $id
     * @return null|\Zend\Db\ResultSet\ResultSetInterface
     */
    public function fetchById($id)
    {
        if (!empty($id)) {

            $select = $this->tableGateway->getSql()->select();
            $select->columns(
                [
                    "id", "addressid", "first", "last", "position",
                    "email", "telephone", "username", "usertype",
                    "password"
                ]
            )->join(
                'tblresellerpartners',
                'tblresellerpartners.partner_id = id'
            )->where([
                "tblresellerpartners.reseller_id" => (int)$id
            ]);

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

In our dump.sql file, we’ve listed a number of users, and one has the id 1. So we know that if we call this method, supplying 1 as the id, then it should return a valid record. Let’s now test that that works.

In UsersTablegatewayTest, we’ll add a new method, as follows:

/**
 * @covers ::fetchById
 */
public function testCanFetchUserById()
{
    $result = $this->usersTable->fetchById(21);

    $this->assertInstanceOf(ResultSetInterface::class, $result);
    $this->assertCount(1, $result);
}

5. Run the Test

Now that everything’s in place, it’s time to execute the test. From your terminal, run the following command to launch the test php vendor/bin/codecept run unit. That will then run all the unit tests, our new one included.

All being well, both assertions will pass, verifying that the code works as anticipated. After that, you could add a range of other assertions, such as passing an invalid id, or one where there’s no matching user.

That’s a Wrap

And that’s how to perform database testing in your Zend Expressive applications, not mocking, using Codeception. I hope that it helps you validate that your database classes do do what you expect that they should. If you need any further information on Codeception, check out the website, or the other Codeception articles here on the blog.


You might also be interested in these tutorials too...

Mon, Aug 22, 2016

How To Use Laravel’s Eloquent ORM with Zend Expressive

Laravel’s Eloquent ORM isn’t likely the first one you think of when using Zend Expressive. You likely think of Zend\Db or Doctrine. But, with a little bit of work, it’s possible to use Eloquent with Expressive. Today’s tutorial shows you how - step-by-step.

Tue, Jul 5, 2016

What I Learned Building a Zend Expressive Application

Zend Expressive is an excellent framework for building modern applications; whether micro or enterprise-sized applications. But that doesn’t mean that it’s the easiest to get up to speed with. Today I’m going to share with you what I’ve learned, building applications using it.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus