PHPackages                             xalaida/pdo-mock - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. xalaida/pdo-mock

ActiveLibrary[Testing &amp; Quality](/categories/testing)

xalaida/pdo-mock
================

Library for mocking database interactions in unit tests.

v0.1(1y ago)66MITPHPPHP ^5.6 | ^7.0 | ^8.0

Since Nov 19Pushed 8mo ago1 watchersCompare

[ Source](https://github.com/xalaida/pdo-mock)[ Packagist](https://packagist.org/packages/xalaida/pdo-mock)[ RSS](/packages/xalaida-pdo-mock/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (3)Used By (0)

PDOMock
=======

[](#pdomock)

[![Packagist](https://camo.githubusercontent.com/d2680f6568c8e54f575bbf549d0c176cbf34e9f628cb49d2a2ad81b9fb503d96/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f78616c616964612f70646f2d6d6f636b)](https://camo.githubusercontent.com/d2680f6568c8e54f575bbf549d0c176cbf34e9f628cb49d2a2ad81b9fb503d96/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f78616c616964612f70646f2d6d6f636b)[![Build](https://camo.githubusercontent.com/9de68d49a013881d8f65751d9ece47e3b9484474b1f5ce4d2011547e5bf92746/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f78616c616964612f70646f2d6d6f636b2f63692e79616d6c3f6272616e63683d6d6173746572)](https://camo.githubusercontent.com/9de68d49a013881d8f65751d9ece47e3b9484474b1f5ce4d2011547e5bf92746/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f78616c616964612f70646f2d6d6f636b2f63692e79616d6c3f6272616e63683d6d6173746572)[![Coverage](https://camo.githubusercontent.com/4af6b48c9a143553390d88cec277266de4f0a373d99f5c66ed58187c2f8f27c5/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f78616c616964612f70646f2d6d6f636b)](https://camo.githubusercontent.com/4af6b48c9a143553390d88cec277266de4f0a373d99f5c66ed58187c2f8f27c5/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f78616c616964612f70646f2d6d6f636b)[![License](https://camo.githubusercontent.com/8a38d1c09b47e8720edd1890f2a928bde476b07bac352e146810ef1957498f50/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f78616c616964612f70646f2d6d6f636b)](https://camo.githubusercontent.com/8a38d1c09b47e8720edd1890f2a928bde476b07bac352e146810ef1957498f50/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f78616c616964612f70646f2d6d6f636b)

PDOMock is a PHP library for testing database interactions without relying on an actual database connection.

Unlike higher-level abstractions like the repository pattern, PDOMock validates database queries at the SQL level, providing greater control and insights into query execution.

This testing technique dramatically accelerates test suite performance and helps identify common issues such as N+1 queries.

Mainly inspired by the Go library [SQL-mock](https://github.com/DATA-DOG/go-sqlmock).

🔍 Overview
----------

[](#-overview)

- Supports any SQL dialect
- Supports most PDO features
- Works with most popular ORMs
- PHPUnit integration
- Supports all PHP versions from 5.6
- No dependencies

🚀 Installation
--------------

[](#-installation)

Install the library using Composer:

```
composer require xalaida/pdo-mock
```

📽️ Example Usage
----------------

[](#️-example-usage)

Here’s an example of how to use PDOMock in your test cases. Let's assume we have the following service that interacts with the database via PDO:

```
use PDO;

class BookService
{
    private PDO $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function findById(int $id): array
    {
        $statement = $this->pdo->prepare('SELECT * FROM "books" WHERE "id" = :id');
        $statement->bindValue('id', $id);
        $statement->execute();

        return $statement->fetch(PDO::FETCH_ASSOC);
    }
}
```

Now, we can write a test for this service:

```
use PHPUnit\Framework\Attributes\Test;

class BookServiceTest
{
    #[Test]
    public function itShouldFindBookById(): void
    {
        $pdo = new PDOMock();

        $pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
            ->with(['id' => 7])
            ->willFetch([
                ['id' => 7, 'title' => 'The Forest Song']
            ]);

        $bookService = new BookService($pdo);

        $book = $bookService->findById(7);

        static::assertEquals(7, $book['id']);
        static::assertEquals('The Forest Song', $book['title']);
    }
}
```

🧾 Documentation
---------------

[](#-documentation)

#### Query Expectation

[](#query-expectation)

PDOMock requires that you set up expectations for each query. To define a simple query expectation, use the `expect` method:

```
use Xalaida\PDOMock\PDOMock;

$pdo = new PDOMock();

$pdo->expect('SELECT * FROM "books"');
```

By default, queries are validated by an exact string match. However, if the query is written in a different format (e.g., multiline), the test will fail. To allow for more flexibility, you can use `toMatchRegex`:

```
$pdo->expect('SELECT * FROM "books" LIMIT 1')
    ->toMatchRegex();
```

This will match the query regardless of whitespace formatting:

```
$pdo->query('
    SELECT * FROM "books"
    LIMIT 1
');
```

And also allows to provide regex placeholders if you want to skip some parts of the query:

```
$pdo->expect('INSERT INTO "books" ({{ .* }}) VALUES ({{ .* }})')
    ->toMatchRegex();
```

**Note:** Be cautious when using `toMatchRegex` as it will also strip whitespace from quoted values.

For "write" queries, it's recommended to use a strict query comparator.

Keep in mind that the query comparator **does not use any SQL parsers**, so you should manually verify that all queries are valid SQL.

The expect method works with any PDO method, including exec, query, or prepared statements. To verify that a statement was prepared, you can specify this manually:

```
$pdo->expect('SELECT * FROM "books" LIMIT 1')
    ->toBePrepared();
```

#### Parameters Validation

[](#parameters-validation)

You can validate query parameters using the `with` method, which allows you to pass an array of parameter values and types:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
    ->with(['id' => 7]);
```

For anonymous placeholders (?), use this syntax:

```
$pdo->expect('SELECT * FROM "books" WHERE "year" = ? AND "status" = ?')
    ->with([2020, 'published']);
```

You can also specify the parameter types:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
    ->with(['id' => 7], ['id' => PDO::PARAM_INT]);
```

By default, parameters are validated using a strict comparator that checks both values and types. For a looser comparison, you can use `toMatchParamsLoosely`:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
    ->with(['id' => 7])
    ->toMatchParamsLoosely();
```

This will pass even if the value is cast to a different type (e.g., '7' instead of 7).

Alternatively, use `toMatchParamsNaturally` to allow automatic type matching:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
    ->with(['id' => 7])
    ->toMatchParamsNaturally();
```

For manual validation, you can use a callback:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = ?')
    ->with(function (array $params, array $types) {
        static::assertSame(7, $params[1]);
        static::assertSame(PDO::PARAM_INT, $types[1]);
    });
```

Validation fails only if the callback returns `false`. Additionally, the `$params` and `$types` arrays use a 1-based index, consistent with PDO bind functions.

#### Result Set Simulation

[](#result-set-simulation)

To simulate query results, use the `willFetch` method:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id')
    ->with(['id' => 7])
    ->willFetch([
        ['id' => 7, 'title' => 'The Forest Song']
    ]);
```

For more complex result sets, you can use a `ResultSet` instance:

```
use Xalaida\PDOMock\ResultSet;

$pdo->expect('SELECT * FROM "books" LIMIT 3')
    ->willFetch(
        (new ResultSet())
            ->setCols(['id', 'title'])
            ->setRows([
                [1, 'The Forest Song'],
                [2, 'Kaidash’s Family'],
                [3, 'Shadows of the Forgotten Ancestors'],
            ])
    );
```

#### Insert, Update, Delete Queries

[](#insert-update-delete-queries)

For insert queries, specify the insert ID:

```
$pdo->expect('INSERT INTO "books" ("title") VALUES (?)')
    ->with(['The Forest Song'])
    ->willInsertId(7);
```

After execution, the `$pdo->lastInsertId()` method will return 7.

For update and delete queries, you can specify the number of affected rows:

```
$pdo->expect('UPDATE "books" SET "status" = :status WHERE "year" = :year')
    ->with(['year' => 2020, 'status' => 'draft'])
    ->willAffect(5);
```

#### Transaction Management

[](#transaction-management)

You can verify transaction behavior with the following methods: `expectBeginTransaction`, `expectCommit`, and `expectRollback`. Here's an example:

```
$pdo->expectBeginTransaction();
$pdo->expect('INSERT INTO "books" ("title") VALUES ("Kaidash’s Family")');
$pdo->expectCommit();
```

#### Error Simulation

[](#error-simulation)

To simulate query exceptions, use the `willFail` method:

```
$pdo->expect('INSERT INTO "books" ("id", "title") VALUES (1, null)')
    ->willFail(PDOMockException::fromErrorInfo(
        'SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: books.title',
        '23000',
        'NOT NULL constraint failed: books.title',
        19
    ));
```

#### Post-Execution Assertions

[](#post-execution-assertions)

To verify that all expected queries were executed, use `assertExpectationFulfilled`:

```
$pdo->expect('SELECT * FROM "books" WHERE "id" = :id');
$pdo->assertExpectationFulfilled();
```

#### Default Comparators

[](#default-comparators)

You can set default comparators that will apply to all future queries:

```
use Xalaida\PDOMock\PDOMock;
use Xalaida\PDOMock\QueryComparatorRegex;
use Xalaida\PDOMock\ParamComparatorNatural;

PDOMock::useQueryComparator(new QueryComparatorRegex());
PDOMock::useParamComparator(new ParamComparatorNatural());
```

#### Integration with PHPUnit

[](#integration-with-phpunit)

If you're using PHPUnit, you may want to integrate its assertion mechanism with PDOMock. To do so, register the extension in your PHPUnit configuration file:

```

```

Alternatively, you can manually configure it in your `TestCase` class:

```
use PHPUnit\Framework\TestCase as BaseTestCase;
use Xalaida\PDOMock\Adapter\PHPUnit\PHPUnitAdapter;
use Xalaida\PDOMock\PDOMock;

class TestCase extends BaseTestCase
{
    public static function setUpBeforeClass(): void
    {
        PDOMock::useAdapter(new PHPUnitAdapter());
    }
}
```

📜 License
---------

[](#-license)

The MIT License (MIT). Please see [LICENSE](LICENSE) for more information.

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance51

Moderate activity, may be stable

Popularity9

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

538d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/28da65e8fb67327a4aecc884be2d4d14d719ed0b393ec9c4febe0f91b9750eb5?d=identicon)[xalaida](/maintainers/xalaida)

---

Top Contributors

[![xalaida](https://avatars.githubusercontent.com/u/31131784?v=4)](https://github.com/xalaida "xalaida (387 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/xalaida-pdo-mock/health.svg)

```
[![Health](https://phpackages.com/badges/xalaida-pdo-mock/health.svg)](https://phpackages.com/packages/xalaida-pdo-mock)
```

###  Alternatives

[phpspec/prophecy

Highly opinionated mocking framework for PHP 5.3+

8.5k551.7M682](/packages/phpspec-prophecy)[vimeo/psalm

A static analysis tool for finding errors in PHP applications

5.8k77.5M6.7k](/packages/vimeo-psalm)[brianium/paratest

Parallel testing for PHP

2.5k118.8M754](/packages/brianium-paratest)[beberlei/assert

Thin assertion library for input validation in business models.

2.4k96.9M571](/packages/beberlei-assert)[mikey179/vfsstream

Virtual file system to mock the real file system in unit tests.

1.4k108.0M2.7k](/packages/mikey179-vfsstream)[orchestra/testbench

Laravel Testing Helper for Packages Development

2.2k39.1M32.1k](/packages/orchestra-testbench)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
