Andrew
Andrew

Reputation: 238717

How to start testing Zend Framework Models?

How do I begin testing my models in a Zend Framework 1.8+ application?

Let's say I have my application set up to start testing. I have already tested a controller, so I know it works. I have all my controllers extending my ControllerTestCase.php file:

<?php
require_once 'Zend/Application.php';
require_once 'Zend/Test/PHPUnit/ControllerTestCase.php';

abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
    public $application;

    public function setUp()
    {
        $this->application = new Zend_Application(
            APPLICATION_ENV,
            APPLICATION_PATH . '/configs/application.ini'
        );

        $this->bootstrap = array($this, 'appBootstrap');
        parent::setUp();
    }

    public function appBootstrap()
    {
        $this->application->bootstrap();
    }

    public function tearDown()
    {
        Zend_Controller_Front::getInstance()->resetInstance();

        $this->resetRequest();
        $this->resetResponse();

        $this->request->setPost(array());
        $this->request->setQuery(array());
        parent::tearDown();
    }
}

But now I want to start testing my models. It seems like my ModelTestCase.php would not extend Zend_Test_PHPUnit_ControllerTestCase but rather a Zend_Test_PHPUnit_ModelTestCase, but no such class exists that I know of. How can I start testing my Zend Framework models?

Upvotes: 2

Views: 2421

Answers (1)

Bill Karwin
Bill Karwin

Reputation: 562330

There is a base ControllerTestCase provided for you because there are complex steps needed to setup and tear down the environment for testing a controller. The input is a mock HTTP request, and the output is rendered HTML that you need to scrape to find expected content.

A Model is more like a plain old PHP object. There's less environment to set up. The interface is simply method calls to the object.

So I would start a TestCase class that extends PHPUnit's plain TestCase, and start by adding at least one test method (as an empty function) for each method in your Model class. You will eventually have many test methods for each method in your Model class, but creating the empty test methods is a good way to keep from forgetting some of your Model methods.

Note that a Model is not a Table -- a Model typically uses one or more Table objects. By following this pattern, you have the opportunity to create mock objects for Tables so you can run the test suite without requiring a live connection to a database.

Here's an example of setting up a mock Table object, which is hardcoded to return a synthetic data set instead of a data set from a database.

<?php

class MyModelTest extends PHPUnit_Framework_TestCase
{
  protected $_model;

  public function setUp()
  {
    $foo = $this->getMock('FooTable', array('find'));
    $foo->expects($this->any())
        ->method('find')
        ->will($this->returnValue(array("id"=>"123")));

    $this->_model = new MyModel();
    $this->_model->setFooTable($foo);
  }

  public function testCountElements()
  {
    $this->_model->get(123);
    $n = $this->_model->countElements();
    $this->assertEquals(1, $n);
  }

  public function testAsArray()
  {
    $this->_model->get(123);
    $a = $this->_model->asArray();
    $this->assertType('array', $a);
  }

  public function testAddElement()
  {
    // ...etc.
  }

  public function testGetElement()
  {
    // ...etc.
  }

}

Upvotes: 7

Related Questions