Mocking drupal database queries

Posted: 2014-03-07 10:15:00

formatting issue will update the code examples soon

I have a Class I want to test with phpunit but it makes several queries to a drupal database. I rather not bootstrapdrupal just to make sure this Class is returning the results as expected.

For example the SiteClass has a method called index. That method takes the uuid for a user and finds all the sites related to that user. Then using that uuid I have some other non drupal data that relates to it. So my class might look like this

//Foo.php
public function getSitesAndOtherDataForUser($uuid) {
$output = db_query(some query here);
return array('data' => $output)
}

But this is hard to test quickly in phpunit without touching the database. But I do not want to test the database. I know db_query works. I know the database layer works. I just want to verify this class is getting the request, getting information and then passing me back the right data format.

One way to do that is to make a Repository class that wraps all your database queries into methods.

So the class SiteClass has a constructor that allows the injection of the repository class for example

//Foo.php
public function __construct(SiteRepository $repo = null)

{
$this->repo = ($repo == null) ? new SiteRepository() : $repo;
}

This then turns the above function into

//Foo.php
public function getSitesAndOtherDataForUser($uuid) {
$output = $this->repo->getSitesForUserUuid($uuid)
return array('data' => $output)
}

And this then allows me to instantiate in a phpunit test the same Repo but using Mockery so my unit test would look like this

//FooTest.php
public function setUp()

{
$this->repo = Mockery::mock('SiteRepository')
}

And later call to that method in the mocked class

//FooTest.php
public function test_getSitesAndOtherDataForUser()

{
$this->repo->shouldReceive('getSitesForUserUuid')->once()->andReturn(array(1,2,3));
}

This then allows me to quickly test how my code is dealing with the output. Maybe there is a filter, or other relations I am trying to pull in. As far as testing that the data structure is correct etc I save that for a test for that.

The Repository Class can look like this if using EntityQuery

//SiteRepository.php

public $eq;

function __construct(\EntityFieldQuery $eq = null) {

$this->eq = ($eq == null) ? new \EntityFieldQuery() : $eq;

}

//Later on I can offer a method

functiongetSitesForUserUuid($uuid){

$this->eq = do some query

}

//if we are not using EQ then just do your db_query in there

function getSitesForUserUuid($uudi) {

$results = db_query(foo);

return $results;

}


Tags:

testing