Skip to content

Herman J. Radtke III

Mocking Zend Framework's Row and Rowset objects

If you separate your business logic from your data access logic, the last thing you want to do is make your business logic unit tests reliant on the database.  This is normally not a big deal: retrieve the data, store it in an array and pass it off to the class with the business logic.  Mocking the data for the unit test simply requires you to hardcode from array information in the test.  However, I recently ran into a case where I wanted to pass Zend_Db_Table_Row and Zend_Db_Table_Row objects to the business logic and mocking them was not so easy.

 array(
                'first_name' => 'Herman',
                'last_name' => 'Radtke',
                'email' => 'herman@example.com'
            )
        );

        $row = new My_ZendDbTable_Row_TestMockRow($data);
        $this->assertEquals('Herman', $row->first_name);
        $this->assertEquals('Radtke', $row->last_name);
        $this->assertEquals('herman@example.com', $row->email);
    }
}

Creating a mock row object is much like hardcoding an array.   Define an array that has a single key 'data' that contains an array as a value.  Inside this array, the database column name is the array key and the database column value is the array value.

That class works great for mocking a single row object, but I still needed a solution for multiple row objects.  I expected to find a class similar to My_ZendDbTable_Row_TestMockRow for the purposes of testing Zend_Db_Table_Rowset, but none existed.  Fortunately, it took only a few minutes to create my own.  All one has to do is specify the name of the row class for the rowset class to use.

 array(
                array(
                    'id' => 123456
                ),
                array(
                    'id' => 123457
                ),
                array(
                    'id' => 123458
                ),
                array(
                    'id' => 123459
                ),
                array(
                    'id' => 123460
                )
            )
        ));

        $id = 123456;
        foreach ($rowset as $row) {
            $this->assertTrue(($row instanceof My_ZendDbTable_Row_TestMockRow));
            $this->assertEquals($id, $row->id);
            $id++;
        }
    }
}

The array passed to the mock rowset has a similar structure to the one we used above.  The only difference is that we have multiple arrays, inside the 'data' array, each representing one row.   For testing purposes, I created an 'id' field.   I normally would not ever use an artificial key field inside a business logic class since that value is very dependent on the database.

I created a ZendDbTableMockRowset class in my projects test/mocks directory so I can use it in multiple test files.  I also copied My_ZendDbTable_Row_TestMockRow into the test/mocks directory so I would not be dependent on the external tests from Zend Framework.  Now mocking Row or Rowset objects is just as fast as mocking arrays.