Skip to content

Introduction

Jarret Byrne edited this page May 20, 2017 · 4 revisions

Wye is a library that can be used to test database-driven PHP without the need for an actual database. By mocking the core PDO and PDOStatement classes, Wye allows you to test scenarios with custom-defined query results and inspect information about each executed query.

Setup is quick and easy, and the interface is intuitive.

Installation

Wye is registered with Packagist and can be installed with Composer. Run the following on the command line:

composer require --dev stratedge/wye

Once Wye has been included in your project, just make sure to require Composer's autoloader:

require_once 'vendor/autoload.php';

Basic Usage

1. Replace Native PDO

In order for Wye to mock the existence of a database, the native PDO must be replaced with Wye's PDO, which extends and implements the interface of its native counterpart. The implementation will vary depending on how your project is architected, but generating a Wye PDO is easy with Wye::makePDO():

use Stratedge\Wye\Wye;

//Generate a Mock PDO object
$pdo = Wye::makePDO();

$pdo instanceof \PDO; //true

//Inject $pdo into your database layer in place of the native PDO
Database::setConnection($pdo);

2. Define Query Results

Since Wye will take the place of the database, it needs to be told what data to return when queries are executed. The Result class makes it super easy to define query results and attach them back to the Wye:

use Stratedge\Wye\Wye;

//Define response to first expected query, which will be an INSERT
$first_query_result = Wye::makeResult();
$first_query_result->setLastInsertId(12)->attach();

//Define response to second expected query, which will be a SELECT
$second_query_result = Wye::makeResult();
$second_query_result->addRow([
    'id' => 12,
    'type' => 'Pumper',
    'apparatus' => 'Engine 7'
])->attach();

NOTE: Always attach() your results, otherwise they will not be used.

3. Execute Your Queries

Now that Wye is set up with some results, call the code that you wish to test and all the queries executed will skip the database and get results from Wye instead. It's all transparent, your code won't know the difference and will behave like it really was talking to a database.

//Running the first query uses the first result object attached to Wye
Database::insert(
    'INSERT INTO `apparatus` (`type`, `apparatus`) VALUES (:type, :apparatus)',
    ['type' => 'Squad', 'apparatus' => 'Rescue 1']
);

$id = Database::getLastInsertId(); //12

//Running the second query uses the second result object attached to Wye
$row = Database::select('SELECT * FROM `apparatus` WHERE `id` = :id', ['id' => $id]);

echo $row->id; //12
echo $row->type; //Pumper
echo $row->apparatus; //Engine 7

4. Inspect Executed Queries

Wye does more than just stand in for your database - it captures all kinds of information about how your code interacts with the database, too. You can use this information for debugging as well as testing assumptions in unit tests. You could inspect individual query statements, parameter bindings, or transaction information, just to name a few.

Here's an example of asserting that the first query run is an insert and that it binds two parameters correctly:

use Stratedge\Wye\Wye;

//Inside your test method...

$statement = Wye::getStatementAtIndex(0);

//Test the query that was run was an INSERT
$this->assertStringStartsWith('INSERT', $statement->getStatement());

//Make sure 2 parameters were bound
$this->assertCount(2, $statement->getBindings());

$bindings = $statement->getBindings();

//Test info of first binding
$this->assertSame('type', $bindings[0]->getParameter());
$this->assertSame('Squad', $bindings[0]->getValue());

//Test info of second binding
$this->assertSame('apparatus', $bindings[1]->getParameter());
$this->assertSame('Rescue 1', $bindings[1]->getValue());

5. Reset Wye

When you are running many tests that work on the same database connection, it's no good if the setup from one test bleeds into the next. Instead, it is best to reset Wye to its original, clean state before running each test by calling Wye::reset():

use Stratedge\Wye\Wye;

Wye::reset();

//Wye is now clean for the next test