PHPackages                             marko/testing - 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. marko/testing

ActiveMarko-module[Testing &amp; Quality](/categories/testing)

marko/testing
=============

Testing utilities for the Marko framework - fakes, assertions, and Pest integration

0.7.0(4w ago)072↓60%20MITPHPPHP ^8.5

Since Mar 25Pushed 4w agoCompare

[ Source](https://github.com/marko-php/marko-testing)[ Packagist](https://packagist.org/packages/marko/testing)[ RSS](/packages/marko-testing/feed)WikiDiscussions develop Synced 3w ago

READMEChangelogDependencies (24)Versions (18)Used By (20)

marko/testing
=============

[](#markotesting)

Testing utilities for Marko---reusable fakes with built-in assertions that eliminate test boilerplate.

Overview
--------

[](#overview)

`marko/testing` provides a set of in-memory fakes that replace real infrastructure dependencies during tests. Instead of mocking interfaces by hand or spinning up real services, you drop in a fake, run your code, and call assertion methods directly on the fake. This removes hundreds of lines of boilerplate and keeps tests focused on behavior.

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

[](#installation)

```
composer require marko/testing --dev
```

Available Fakes
---------------

[](#available-fakes)

`FakeEventDispatcher`, `FakeMailer`, `FakeQueue`, `FakeSession`, `FakeCookieJar`, `FakeLogger`, `FakeConfigRepository`, `FakeAuthenticatable`, `FakeUserProvider`, `FakeGuard`

Usage
-----

[](#usage)

### FakeEventDispatcher

[](#fakeeventdispatcher)

```
use Marko\Testing\Fake\FakeEventDispatcher;

$dispatcher = new FakeEventDispatcher();
$dispatcher->dispatch(new OrderPlaced($order));

$dispatcher->assertDispatched(OrderPlaced::class);
$dispatcher->assertDispatchedCount(OrderPlaced::class, 1);
$dispatcher->assertNotDispatched(OrderShipped::class);
```

### FakeMailer

[](#fakemailer)

```
use Marko\Testing\Fake\FakeMailer;

$mailer = new FakeMailer();
$mailer->send($message);

$mailer->assertSent(WelcomeEmail::class);
$mailer->assertSentCount(WelcomeEmail::class, 1);
$mailer->assertNothingSent();
```

### FakeQueue

[](#fakequeue)

```
use Marko\Testing\Fake\FakeQueue;

$queue = new FakeQueue();
$queue->push(new ProcessOrder($order));

$queue->assertPushed(ProcessOrder::class);
$queue->assertPushedCount(ProcessOrder::class, 1);
$queue->assertNotPushed(SendInvoice::class);
$queue->assertNothingPushed();
```

### FakeSession

[](#fakesession)

```
use Marko\Testing\Fake\FakeSession;

$session = new FakeSession();
$session->put('user_id', 42);

$value = $session->get('user_id'); // 42
$session->forget('user_id');
```

### FakeCookieJar

[](#fakecookiejar)

```
use Marko\Testing\Fake\FakeCookieJar;

$cookies = new FakeCookieJar();
$cookies->set('token', 'abc123');

$value = $cookies->get('token'); // 'abc123'
```

### FakeLogger

[](#fakelogger)

```
use Marko\Testing\Fake\FakeLogger;

$logger = new FakeLogger();
$logger->info('User logged in');
$logger->error('Something failed');

$logger->assertLogged('User logged in');
$logger->assertNothingLogged();
```

### FakeConfigRepository

[](#fakeconfigrepository)

```
use Marko\Testing\Fake\FakeConfigRepository;

$config = new FakeConfigRepository([
    'auth.defaults.guard' => 'web',
    'app.name' => 'Marko',
]);

$value = $config->get('auth.defaults.guard'); // 'web'
```

### FakeAuthenticatable

[](#fakeauthenticatable)

```
use Marko\Testing\Fake\FakeAuthenticatable;

$user = new FakeAuthenticatable(id: 1, password: 'hashed-secret');

$user->getAuthIdentifier(); // 1
$user->getAuthPassword();   // 'hashed-secret'
```

### FakeUserProvider

[](#fakeuserprovider)

```
use Marko\Testing\Fake\FakeUserProvider;
use Marko\Testing\Fake\FakeAuthenticatable;

$user = new FakeAuthenticatable(id: 1);
$provider = new FakeUserProvider($user);

$found = $provider->retrieveById(1); // returns $user
```

### FakeGuard

[](#fakeguard)

```
use Marko\Testing\Fake\FakeGuard;
use Marko\Testing\Fake\FakeAuthenticatable;

$guard = new FakeGuard(name: 'web', attemptResult: true);

// Set a user directly
$user = new FakeAuthenticatable(id: 1);
$guard->setUser($user);
$guard->assertAuthenticated();

// Test login attempt
$guard->attempt(['email' => 'user@example.com', 'password' => 'secret']);
$guard->assertAttempted();

// Assert no user logged in
$guard->logout();
$guard->assertGuest();
$guard->assertLoggedOut();
```

### KnownDriversValidator

[](#knowndriversvalidator)

```
use Marko\Testing\KnownDrivers\KnownDriversValidator;

KnownDriversValidator::assertDocsUrlsResolveToValidPattern(
    __DIR__ . '/../known-drivers.php',
);

KnownDriversValidator::assertSkeletonSuggestContainsAll(
    __DIR__ . '/../known-drivers.php',
    __DIR__ . '/../../skeleton/composer.json',
);
```

API Reference
-------------

[](#api-reference)

### FakeEventDispatcher

[](#fakeeventdispatcher-1)

- `dispatch($event): void` — Record a dispatched event
- `dispatched(string $class): array` — Return all dispatched events of a class
- `assertDispatched(string $class): void` — Assert an event was dispatched
- `assertNotDispatched(string $class): void` — Assert an event was not dispatched
- `assertDispatchedCount(string $class, int $count): void` — Assert exact dispatch count

### FakeMailer

[](#fakemailer-1)

- `send($message): void` — Record a sent message
- `assertSent(string $class): void` — Assert a message was sent
- `assertNothingSent(): void` — Assert no messages were sent
- `assertSentCount(string $class, int $count): void` — Assert exact sent count

### FakeQueue

[](#fakequeue-1)

- `push($job): void` — Record a pushed job
- `assertPushed(string $class): void` — Assert a job was pushed
- `assertNotPushed(string $class): void` — Assert a job was not pushed
- `assertPushedCount(string $class, int $count): void` — Assert exact pushed count
- `assertNothingPushed(): void` — Assert no jobs were pushed

### FakeLogger

[](#fakelogger-1)

- `info(string $message): void`, `error()`, `warning()`, etc. — Record log entries
- `assertLogged(string $message): void` — Assert a message was logged
- `assertNothingLogged(): void` — Assert nothing was logged

### FakeGuard

[](#fakeguard-1)

- `new FakeGuard(string $name, bool $attemptResult)` — Create guard; `$attemptResult` controls what `attempt()` returns
- `setUser(?AuthenticatableInterface $user): void` — Set the current authenticated user
- `attempt(array $credentials): bool` — Record credentials attempt and return configured result
- `login(AuthenticatableInterface $user): void` — Log in a user directly
- `logout(): void` — Clear current user and record logout
- `assertAuthenticated(): void` — Assert a user is currently authenticated
- `assertGuest(): void` — Assert no user is authenticated
- `assertAttempted(?callable $callback = null): void` — Assert attempt() was called, optionally matching credentials via callback
- `assertNotAttempted(): void` — Assert attempt() was never called
- `assertLoggedOut(): void` — Assert logout() was called

### KnownDriversValidator

[](#knowndriversvalidator-1)

- `assertDocsUrlsResolveToValidPattern(string $knownDriversPath): void` — Assert every key in `known-drivers.php` follows the `marko/*` prefix pattern
- `assertSkeletonSuggestContainsAll(string $knownDriversPath, string $skeletonComposerPath): void` — Assert the skeleton's `suggest` block contains every entry from `known-drivers.php` with matching descriptions

Pest Expectations
-----------------

[](#pest-expectations)

`marko/testing` ships Pest custom expectations that are auto-loaded via `autoload.files`.

```
use Marko\Testing\Fake\FakeEventDispatcher;
use Marko\Testing\Fake\FakeGuard;
use Marko\Testing\Fake\FakeMailer;
use Marko\Testing\Fake\FakeQueue;
use Marko\Testing\Fake\FakeLogger;

// FakeEventDispatcher
expect($dispatcher)->toHaveDispatched(OrderPlaced::class);

// FakeMailer
expect($mailer)->toHaveSent();
expect($mailer)->toHaveSent(fn ($msg) => $msg instanceof WelcomeEmail);

// FakeQueue
expect($queue)->toHavePushed(ProcessOrder::class);

// FakeLogger
expect($logger)->toHaveLogged('User logged in');

// FakeGuard
expect($guard)->toHaveAttempted();
expect($guard)->toHaveAttempted(fn ($creds) => $creds['email'] === 'user@example.com');
expect($guard)->toBeAuthenticated();
```

Documentation
-------------

[](#documentation)

Full usage, API reference, and examples: [marko/testing](https://marko.build/docs/packages/testing/)

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance94

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community22

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 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

Every ~4 days

Recently: every ~13 days

Total

16

Last Release

28d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/437029?v=4)[Mark Shust](/maintainers/markshust)[@markshust](https://github.com/markshust)

---

Top Contributors

[![markshust](https://avatars.githubusercontent.com/u/437029?v=4)](https://github.com/markshust "markshust (16 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/marko-testing/health.svg)

```
[![Health](https://phpackages.com/badges/marko-testing/health.svg)](https://phpackages.com/packages/marko-testing)
```

PHPackages © 2026

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