patchlevel/event-sourcing-phpunit
A dev testing toolkit for patchlevel/event-sourcing that lets you test aggregates and subscribers with clear given/when/then notation. Dispatch commands through #[Handle] methods, assert aggregate state with closures, and use subscriber setup, run, and teardown utilities.
Architecture fit. This is a dev-only PHPUnit test harness for patchlevel/event-sourcing aggregates and subscribers. It has no production runtime footprint and only fits if the application already uses (or commits to) the Patchlevel event-sourcing library and its #[Handle] command/event conventions. For teams on that stack, it replaces bespoke aggregate test scaffolding with a given/when/then DSL; for teams on Spatie, EventSauce, or custom event sourcing, it is not applicable.
Integration feasibility. Technically straightforward: composer require --dev, extend the provided test case, and write aggregate tests. The real feasibility question is ecosystem validation, not mechanics. One star, zero dependents, and a single maintainer mean we would be an early adopter rather than a fast follower. The 1.0.x release line and Stryker mutation-testing badge suggest deliberate quality practices, but that is not a substitute for production usage evidence.
Technical risk.
when dispatching through #[Handle] methods and subscriber setup/run/teardown utilities depend on Patchlevel’s conventions; upstream changes can break tests in non-obvious ways.Key questions.
patchlevel/event-sourcing versions are supported, and is there a CI matrix?TPM recommendation: conditional pilot, not broad adoption. Proceed only if Patchlevel event sourcing is already strategic. Budget for an internal wrapper and an exit path.
Stack fit. Best fit is a Laravel/PHP codebase using PHPUnit and the Patchlevel event-sourcing library, with aggregates and subscribers already following #[Handle] conventions. If the team uses Pest, confirm compatibility first; if it uses a different event-sourcing library, stop here.
Migration path. Do not rewrite the suite. Introduce the package in one bounded context, wrap the provided test case in an internal base class (for example DomainAggregateTestCase), and migrate the highest-value aggregate tests first. Keep existing tests running in parallel until the new notation proves equivalent coverage. Treat the wrapper as the seam that isolates us from upstream API changes.
Compatibility. Pin exact versions in composer.json and commit the lockfile. Add a CI job that runs the package’s supported PHP/PHPUnit matrix, plus one job on our next planned PHPUnit major to surface upgrade friction early. Verify the Patchlevel event-sourcing version constraint before the pilot; a mismatch is a hard blocker.
Sequencing.
Maintenance. Runtime maintenance is near zero because it is dev-only. Test-infrastructure maintenance is not: we own version pinning, PHPUnit upgrade compatibility, and any wrapper code. Plan a quarterly dependency review and assign a named owner. The single-maintainer risk should be recorded in the dependency risk register.
Support. Expect community-grade support: documentation site, README, and issues, with no SLA. Internal ramp-up material and examples are our responsibility. Escalation options are limited to upstream issues, a fork, or replacing the harness.
Scaling. The package itself does not constrain production scaling. Test-suite scaling is the concern: mutation testing and subscriber setup/teardown can lengthen CI. Plan for parallel test execution and keep mutation testing scoped to critical aggregates rather than the whole suite.
Failure modes.
Ramp-up. Low for developers already comfortable with given/when/then and event sourcing; moderate for those new to aggregates. A half-day workshop plus one worked example per bounded context should suffice. The main onboarding cost is teaching the internal wrapper conventions, not the package API.
How can I help you explore Laravel packages today?