Mock function testing in Drupal

by aaron on Thu, 04/24/2008 - 08:32

Talking with one of my coworkers yesterday, we found ourselves in need of testing a drupal module in isolation.

This module had a few complex elements to it, in addition to the regular drupal node functionality, such as web service calls and permissions checks, which made testing the module itself far too dependent on third party systems, and made testing itself exceptionally brittle.

Introducing PHPMockFunction

I've written a preliminary pass at mocking functions in drupal. This allows you to focus entirely on your module in an isolated container, and allows you to mock up functions (or retain them, for that matter).

Functions can be new, or they can already exist. That's right. You heard me.

Wait, how do you do that?

Through the magic of the PECL runkit extension, one can selectively override certain functions (either native php functions or userspace ones) in certain conditions. This is NEVER something one should do in production, but in a testing environment, it can be an incredibly userful tool.

PHP mock objects have existed in simpletest and PHPUnit for a long while, but I hadn't seen anything that provided the same functionality for php functions.

So we wrote it.

A mock function example:

  require_once("PHPMockFunction.php");
  require_once("../mymodule.module");
 
  $dbMock = PHPMockFunction::mock('db_query');
  $dummyResource = new stdClass();
  $dbMock->expects(InvocationRestriction::once())
      ->with('SELECT name,value FROM {foo}')
      ->will(WillAction::returnValue($dummyResource);
  $dummyArrayResult = array("name" => "foo", "value" => "bar");
  $dbFetchArrayMock = PHPMockFunction::mock('db_fetch_array');
    $dbFetchArrayMock->expects(InvocationRestriction::atLeast(1))
      ->with($dummyResource)
      ->will(WillAction::returnValue($dummyArray));

  mymodule_get_foo_results();

What does this mean?

Now you can test your modules without having to rely on the db layer.. True testing in isolation in drupal.

Download PHPMockFunction here and give it a whirl. Feedback is welcome.

Tags: Drupalmock objectstest driven developmenttests

aaron's blog  
    Delicious  Digg  Reddit  Technorati  

Comments

I like your API better than

I like your API better than this "project"
http://www.phppatterns.com/docs/develop/simpletest_mock_functions

however, what's nice about the other "project" is that leverages mock_objects that comes w/simpletest so all sorts of expectations and validation come for free.

Are you going to start a project on this somewhere?

I've set up a project on

I've set up a project on google Code:

http://code.google.com/p/php-mock-function

Excellent!

I submitted a patch, as I'm sure you've seen. Mailing list? I have lot's to discuss that would be useful to capture in project archives.

Douglas, You've got a point,

Douglas,

You've got a point, SimpleUnit's mock objects support is fairly comprehensive, but when I was first prototyping this it became probitive since simpleunit insists on acting on objects, for which none exist when you're mocking a function. My original take on this was an attempt to use either of simplemock or phpmock, but it turned out to be a dead end.

I'd like to kick this off as a project; the above was a sample case, and is definitely a work in progress.

I've set it up as a project on Google Code. If you'd like, ping me on D.O. and I'll set you up as a contributor.

-=A

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options