PHPackages                             eventjet/test-double - 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. eventjet/test-double

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

eventjet/test-double
====================

Reusable PSR-compliant test doubles for HTTP clients, loggers, and SOAP clients

1.9.1(1w ago)05MITPHPPHP &gt;=8.3CI passing

Since Jan 14Pushed 1w ago2 watchersCompare

[ Source](https://github.com/eventjet/test-double)[ Packagist](https://packagist.org/packages/eventjet/test-double)[ RSS](/packages/eventjet-test-double/feed)WikiDiscussions master Synced today

READMEChangelog (10)Dependencies (14)Versions (18)Used By (0)

eventjet/test-double
====================

[](#eventjettest-double)

Reusable PSR-compliant test doubles for PHP — drop-in fakes for HTTP clients, loggers, and SOAP clients with a fluent matcher API and descriptive failure messages.

Requirements
------------

[](#requirements)

- PHP 8.3+
- `ext-soap` (only required when using `TestSoapClient`)

Installation
------------

[](#installation)

```
composer require --dev eventjet/test-double
```

Test Doubles
------------

[](#test-doubles)

ClassImplementsDocumentation`TestLogger`PSR-3 `LoggerInterface`[doc/TestLogger.md](doc/TestLogger.md)`TestHttpClient`PSR-18 `ClientInterface`[doc/TestHttpClient.md](doc/TestHttpClient.md)`TestSoapClient`Custom SOAP client[doc/TestSoapClient.md](doc/TestSoapClient.md)Reusable matchers (`Str::regex()`, `Val::eq()`) are documented in [doc/Matchers.md](doc/Matchers.md).

Quick Start
-----------

[](#quick-start)

### TestLogger

[](#testlogger)

```
use Eventjet\TestDouble\TestLogger;
use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;

final class MyServiceTest extends TestCase
{
    public function testLogsWarningOnFailure(): void
    {
        $logger = new TestLogger();
        $service = new MyService($logger);

        $service->doSomething();

        $result = $logger->once(
            TestLogger::and(
                TestLogger::level(LogLevel::WARNING),
                TestLogger::message('Operation failed')
            )
        );
        self::assertTrue($result);
    }
}
```

### TestHttpClient

[](#testhttpclient)

```
use Eventjet\TestDouble\TestHttpClient;
use GuzzleHttp\Psr7\HttpFactory;
use PHPUnit\Framework\TestCase;

final class MyApiClientTest extends TestCase
{
    public function testFetchesUser(): void
    {
        $factory = new HttpFactory();
        $httpClient = new TestHttpClient();
        $httpClient->map(
            TestHttpClient::path('/api/users/1'),
            $factory->createResponse(200)->withBody(
                $factory->createStream('{"id":1,"name":"John"}')
            )
        );

        $apiClient = new MyApiClient($httpClient);
        $user = $apiClient->getUser(1);

        self::assertSame('John', $user->name);
    }
}
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance98

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 64.7% 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

Every ~41 days

Recently: every ~63 days

Total

11

Last Release

11d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/bf84c6852b03fde91d73c1c04b6dabe5d47167d4994a6cf40c11e5cfd18d07e7?d=identicon)[trinet](/maintainers/trinet)

---

Top Contributors

[![MidnightDesign](https://avatars.githubusercontent.com/u/743172?v=4)](https://github.com/MidnightDesign "MidnightDesign (11 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![wolfgangschaefer](https://avatars.githubusercontent.com/u/26325205?v=4)](https://github.com/wolfgangschaefer "wolfgangschaefer (1 commits)")

---

Tags

psr-3testingphpunithttp clientpsr-18mockstubtest doublelogger

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/eventjet-test-double/health.svg)

```
[![Health](https://phpackages.com/badges/eventjet-test-double/health.svg)](https://phpackages.com/packages/eventjet-test-double)
```

###  Alternatives

[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k488.3M20.8k](/packages/mockery-mockery)[php-mock/php-mock-phpunit

Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.

1718.0M349](/packages/php-mock-php-mock-phpunit)[php-mock/php-mock

PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.

37417.5M83](/packages/php-mock-php-mock)[phake/phake

The Phake mock testing library

4768.0M295](/packages/phake-phake)[kahlan/kahlan

The PHP Test Framework for Freedom, Truth and Justice.

1.1k1.1M235](/packages/kahlan-kahlan)[php-mock/php-mock-mockery

Mock built-in PHP functions (e.g. time()) with Mockery. This package relies on PHP's namespace fallback policy. No further extension is needed.

392.0M86](/packages/php-mock-php-mock-mockery)

PHPackages © 2026

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