Experimental project

This is a sandbox project, which contains experimental code for developer use only.

This is an experiment for exploring possibilities to integrate the third party PHP mock object framework mockery into DrupalWebTestCase. The goal is to provide an easy to use API for testing drupal hooks invoked during DrupalWebTestCase::drupalGet in a stub module.

Installation

Install PHP mockery using PEAR:

sudo pear channel-discover pear.survivethedeepend.com
sudo pear channel-discover hamcrest.googlecode.com/svn/pear
sudo pear install --alldeps deepend/Mockery

This module does not expose an UI. It is not even shown in the module administration page. The module should only be enabled and loaded as part of a test-case requiring it.

Example

When modules expose hooks for other modules to implement, it is good practice to document them in MY_MODULE.api.php file:

/**
 * Hook triggered when running out of ideas.
 * 
 * @return string
 *   Return a list of things to try in response
 */
function hook_MY_MODULE_stand_up_and() {
  return array(
    t('Make coffee'),
    t('Go for a walk'),
  );
}

It is also good practice to write tests to make sure those hooks actually are invoked with the correct arguments and the return value is processed correctly by the module. The usual way to test hooks is to supply stub-module implementing the API. However in order to test for different conditions and return values, it is necessary to either write multiple stub modules (with different behavior) or somehow build the logic into the hook-implementations themselves. The mockery module provides a solution for this problem by providing an easy way to implement flexible stub hooks. The code for MY_MODULE_test.module for our example looks like this:

/**
 * Hook triggered when running out of ideas.
 * 
 * @return string
 *   Return a list of things to try in response
 */
function MY_MODULE_test_stand_up_and() {
  return DrupalMockery::hookStub(__FUNCTION__, func_get_args());
}

Now it is possible to test for different cases using the following test-code (MY_MODULE.test):

class MockeryTestCase extends DrupalWebTestCase {
  protected $profile = 'testing';
  protected $mockery;

  public static function getInfo() {
    return array(
      'name' => 'MY MODULE',
      'description' => 'Test for my module',
      'group' => 'MY MODULE',
    );
  }

  public function setUp() {
    parent::setUp('MY_MODULE', 'MY_MODULE_test');
    $this->mockery = DrupalMockery::mockery($this->databasePrefix);
  }

  public function tearDown() {
    $this->mockery->verifyAndTearDown($this);
    parent::tearDown();
  }

  public function testThatHookIsCalledOnEachPageLoad() {
    $this->mockery->setupModule('MY_MODULE_test', function($module, $mockery) {
      $module->shouldReceiveHook('stand_up_and')->once();
    });

    $this->drupalGet('node');
  }
}

Project information